[LLVMbugs] [Bug 1604] New: C++ virtual tables can' t be optimized away when external functions references part of polymorphic objects

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Fri Aug 10 09:07:26 PDT 2007


http://llvm.org/bugs/show_bug.cgi?id=1604

           Summary: C++ virtual tables can't be optimized away when external
                    functions references part of polymorphic objects
           Product: new-bugs
           Version: unspecified
          Platform: PC
        OS/Version: Windows XP
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: new bugs
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: loufoque at gmail.com
                CC: llvmbugs at cs.uiuc.edu


With this simple C++ code:

#include <cstdio>

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 )            ; <i32> [#uses=0]
        %tmp7 = load i32* %tmp4         ; <i32> [#uses=1]
        %tmp10 = call i32 (i8*, ...)* @printf( i8* getelementptr ([4 x i8]*
@.str1, i32 0, i32 0), i32 %tmp7 )          ; <i32> [#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 )           ; <i32> [#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?


-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list