Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

need better mod/ref info for scanf #1976

Closed
llvmbot opened this issue Aug 10, 2007 · 3 comments
Closed

need better mod/ref info for scanf #1976

llvmbot opened this issue Aug 10, 2007 · 3 comments
Labels
bugzilla Issues migrated from bugzilla code-quality

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Aug 10, 2007

Bugzilla Link 1604
Resolution LATER
Resolved on Oct 15, 2008 11:06
Version unspecified
OS Windows XP
Reporter LLVM Bugzilla Contributor

Extended Description

With this simple C++ code:

#include

struct test
{
int val;
virtual ~test() {}
};

int main()
{
test t;
std::scanf("%d", &t.val);
std::printf("%d\n", t.val);
}

LLVM generates a lot of unneeded things:

target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "i686-pc-linux-gnu"
%struct.__class_type_info_pseudo = type { %struct.__type_info_pseudo }
%struct.__type_info_pseudo = type { i8*, i8* }
%struct.test = type { i32 (...)**, i32 }
@​_ZTV4test = internal constant [4 x i32 (...)] [ i32 (...) null, i32 (...)* bitcast (%struct.__class_type_info_pseudo* @​_ZTI4test to i32 (...)), i32 (...) bitcast (void (%struct.test*)* @​_ZN4testD1Ev to i32 (...)), i32 (...) bitcast (void (%struct.test*)* @​_ZN4testD0Ev to i32 (...)) ], align 8 ; <[4 x i32 (...)]> [#uses=1]
@​_ZTI4test = internal constant %struct.__class_type_info_pseudo { %struct.__type_info_pseudo { i8
inttoptr (i32 add (i32 ptrtoint ([0 x i32 (...)] @​_ZTVN10__cxxabiv117__class_type_infoE to i32), i32 8) to i8*), i8* getelementptr ([6 x i8]* @​_ZTS4test, i32 0, i32 0) } } ; <%struct.__class_type_info_pseudo*> [#uses=1]
@​_ZTVN10__cxxabiv117__class_type_infoE = external constant [0 x i32 (...)] ; <[0 x i32 (...)]> [#uses=1]
@​_ZTS4test = internal constant [6 x i8] c"4test\00" ; <[6 x i8]
> [#uses=1]
@.str = internal constant [3 x i8] c"%d\00" ; <[3 x i8]> [#uses=1]
@.str1 = internal constant [4 x i8] c"%d\0A\00" ; <[4 x i8]
> [#uses=1]

define i32 @​main() {
entry:
%t = alloca %struct.test, align 16 ; <%struct.test*> [#uses=2]
%tmp2 = getelementptr %struct.test* %t, i32 0, i32 0 ; <i32 (...)> [#uses=1]
store i32 (...)
getelementptr ([4 x i32 (...)
]* @​_ZTV4test, i32 0, i64 2), i32 (...)*** %tmp2
%tmp4 = getelementptr %struct.test* %t, i32 0, i32 1 ; <i32*> [#uses=2]
%tmp5 = call i32 (i8*, ...)* @​scanf( i8* getelementptr ([3 x i8]* @.str, i32 0, i32 0), i32* %tmp4 ) ; [#uses=0]
%tmp7 = load i32* %tmp4 ; [#uses=1]
%tmp10 = call i32 (i8*, ...)* @​printf( i8* getelementptr ([4 x i8]* @.str1, i32 0, i32 0), i32 %tmp7 ) ; [#uses=0]
ret i32 0
}

define internal void @​_ZN4testD1Ev(%struct.test* %this) {
entry:
%tmp2 = getelementptr %struct.test* %this, i32 0, i32 0 ; <i32 (...)> [#uses=1]
store i32 (...)
getelementptr ([4 x i32 (...)
]* @​_ZTV4test, i32 0, i64 2), i32 (...)*** %tmp2
ret void
}

define internal void @​_ZN4testD0Ev(%struct.test* %this) {
entry:
%tmp2 = getelementptr %struct.test* %this, i32 0, i32 0 ; <i32 (...)> [#uses=1]
store i32 (...)
getelementptr ([4 x i32 (...)
]* @​_ZTV4test, i32 0, i64 2), i32 (...)*** %tmp2
%tmp56 = bitcast %struct.test* %this to i8* ; <i8*> [#uses=1]
tail call void @​_ZdlPv( i8* %tmp56 )
ret void
}

declare void @​_ZdlPv(i8*)

declare i32 @​scanf(i8*, ...)

declare i32 @​printf(i8*, ...)

None of the internal (apart from string literals) and external constants and the @​_ZN4testD1Ev and @​_ZN4testD0Ev functions are useful at all.
For example, if there is no scanf performed (initialized to 0 instead), we get the following code:

target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "i686-pc-linux-gnu"
%struct.test = type { i32 }
@.str = internal constant [4 x i8] c"%d\0A\00" ; <[4 x i8]*> [#uses=1]

define i32 @​main() {
entry:
%tmp4 = tail call i32 (i8*, ...)* @​printf( i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i32 0 ) ; [#uses=0]
ret i32 0
}

declare i32 @​printf(i8*, ...)

It seems that because scanf takes a pointer to a member of test, the test object must be kept as it is, including the pointer to the vtable, and the vtable itself must thus stay in the code.
However it's only a member of test, not a test object itself, so this is not really needed.
Is this a bug or this is normal behaviour? If it's not a bug, would there be a way to instruct the compiler or extend the language in a way where it would be possible to elide the unneeded bloat?

@lattner
Copy link
Collaborator

lattner commented Aug 12, 2007

The real issue here is that the compiler doesn't know what scanf does. It treats it like it treats any other external function. It doesn't know that it only accesses the pointed to word of memory, for example.

@llvmbot
Copy link
Collaborator Author

llvmbot commented Aug 22, 2008

Does LibCallAliasAnalysis fix this?

@lattner
Copy link
Collaborator

lattner commented Oct 15, 2008

No, LibCallAliasAnalysis is not an AA impl. This bug is a very minor thing, and requires knowing that "%d" stores to 4 bytes etc. I moved this to lib/Target/README.txt, which is where we keep assorted minor hacks.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 3, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla code-quality
Projects
None yet
Development

No branches or pull requests

2 participants