blob: e989ffec43746868cda21168ee1ff072211f0a8d [file] [log] [blame]
; Example from Milanova, Rountev, and Ryder(Precise Call graphs for C programs with Function Pointers)
; Because table is not const, func1, and func2 do not get inlined into main
; ModuleID = 'tt.o'
;RUN: dsaopt %s -dsa-bu -analyze -check-callees=main,func1,func2
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
%struct.parse_table = type { i8*, i32 ()* }
@table = internal global [2 x %struct.parse_table] [%struct.parse_table { i8* getelementptr inbounds ([6 x i8]* @.str, i64 0, i64 0), i32 ()* @func1 }, %struct.parse_table { i8* getelementptr inbounds ([6 x i8]* @.str1, i64 0, i64 0), i32 ()* @func2 }], align 32 ; <[2 x %struct.parse_table]*> [#uses=2]
@.str = private constant [6 x i8] c"name1\00", align 1 ; <[6 x i8]*> [#uses=1]
@.str1 = private constant [6 x i8] c"name2\00", align 1 ; <[6 x i8]*> [#uses=1]
define internal i32 @func1() nounwind {
entry:
%retval = alloca i32 ; <i32*> [#uses=2]
%0 = alloca i32 ; <i32*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i32 1, i32* %0, align 4
%1 = load i32* %0, align 4 ; <i32> [#uses=1]
store i32 %1, i32* %retval, align 4
br label %return
return: ; preds = %entry
%retval1 = load i32* %retval ; <i32> [#uses=1]
ret i32 %retval1
}
define internal i32 @func2() nounwind {
entry:
%retval = alloca i32 ; <i32*> [#uses=2]
%0 = alloca i32 ; <i32*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i32 2, i32* %0, align 4
%1 = load i32* %0, align 4 ; <i32> [#uses=1]
store i32 %1, i32* %retval, align 4
br label %return
return: ; preds = %entry
%retval1 = load i32* %retval ; <i32> [#uses=1]
ret i32 %retval1
}
define internal i32 ()* @find_p_func(i8* %s) nounwind {
entry:
%s_addr = alloca i8* ; <i8**> [#uses=2]
%retval = alloca i32 ()* ; <i32 ()**> [#uses=2]
%0 = alloca i32 ()* ; <i32 ()**> [#uses=3]
%i = alloca i32 ; <i32*> [#uses=6]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i8* %s, i8** %s_addr
store i32 0, i32* %i, align 4
br label %bb3
bb: ; preds = %bb3
%1 = load i32* %i, align 4 ; <i32> [#uses=1]
%2 = sext i32 %1 to i64 ; <i64> [#uses=1]
%3 = getelementptr inbounds [2 x %struct.parse_table]* @table, i64 0, i64 %2 ; <%struct.parse_table*> [#uses=1]
%4 = getelementptr inbounds %struct.parse_table* %3, i32 0, i32 0 ; <i8**> [#uses=1]
%5 = load i8** %4, align 8 ; <i8*> [#uses=1]
%6 = load i8** %s_addr, align 8 ; <i8*> [#uses=1]
%7 = call i32 (...)* bitcast (i32 (i8*, i8*)* @strcmp to i32 (...)*)(i8* %5, i8* %6) nounwind readonly ; <i32> [#uses=1]
%8 = icmp eq i32 %7, 0 ; <i1> [#uses=1]
br i1 %8, label %bb1, label %bb2
bb1: ; preds = %bb
%9 = load i32* %i, align 4 ; <i32> [#uses=1]
%10 = sext i32 %9 to i64 ; <i64> [#uses=1]
%11 = getelementptr inbounds [2 x %struct.parse_table]* @table, i64 0, i64 %10 ; <%struct.parse_table*> [#uses=1]
%12 = getelementptr inbounds %struct.parse_table* %11, i32 0, i32 1 ; <i32 ()**> [#uses=1]
%13 = load i32 ()** %12, align 8 ; <i32 ()*> [#uses=1]
store i32 ()* %13, i32 ()** %0, align 8
br label %bb5
bb2: ; preds = %bb
%14 = load i32* %i, align 4 ; <i32> [#uses=1]
%15 = add nsw i32 %14, 1 ; <i32> [#uses=1]
store i32 %15, i32* %i, align 4
br label %bb3
bb3: ; preds = %bb2, %entry
%16 = load i32* %i, align 4 ; <i32> [#uses=1]
%17 = icmp sle i32 %16, 1 ; <i1> [#uses=1]
br i1 %17, label %bb, label %bb4
bb4: ; preds = %bb3
store i32 ()* null, i32 ()** %0, align 8
br label %bb5
bb5: ; preds = %bb4, %bb1
%18 = load i32 ()** %0, align 8 ; <i32 ()*> [#uses=1]
store i32 ()* %18, i32 ()** %retval, align 8
br label %return
return: ; preds = %bb5
%retval6 = load i32 ()** %retval ; <i32 ()*> [#uses=1]
ret i32 ()* %retval6
}
declare i32 @strcmp(i8*, i8*) nounwind readonly
define i32 @main(i32 %argc, i8** %argv) nounwind {
entry:
%argc_addr = alloca i32 ; <i32*> [#uses=1]
%argv_addr = alloca i8** ; <i8***> [#uses=2]
%retval = alloca i32 ; <i32*> [#uses=1]
%parse_func = alloca i32 ()* ; <i32 ()**> [#uses=3]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i32 %argc, i32* %argc_addr
store i8** %argv, i8*** %argv_addr
%0 = load i8*** %argv_addr, align 8 ; <i8**> [#uses=1]
%1 = getelementptr inbounds i8** %0, i64 1 ; <i8**> [#uses=1]
%2 = load i8** %1, align 1 ; <i8*> [#uses=1]
%3 = call i32 ()* (i8*)* @find_p_func(i8* %2) nounwind ; <i32 ()*> [#uses=1]
store i32 ()* %3, i32 ()** %parse_func, align 8
%4 = load i32 ()** %parse_func, align 8 ; <i32 ()*> [#uses=1]
%5 = icmp ne i32 ()* %4, null ; <i1> [#uses=1]
br i1 %5, label %bb, label %bb1
bb: ; preds = %entry
%6 = load i32 ()** %parse_func, align 8 ; <i32 ()*> [#uses=1]
%7 = call i32 %6() nounwind ; <i32> [#uses=0]
br label %bb1
bb1: ; preds = %bb, %entry
br label %return
return: ; preds = %bb1
%retval2 = load i32* %retval ; <i32> [#uses=1]
ret i32 %retval2
}