linux/x86-64 codegen support

PR1711 is an x86 codegen problem that is blocking adoption of llvm-gcc by people using linux on x86-64 boxes. Could someone with access to one of these boxes take a look? I'll help try to debug this, but I don't have access to a machine. I bet it's a small tweak required in the x86 backend.

Thanks!

-Chris

libcpp/charset.c:631 turns into:

      %tmp16 = tail call i64 @strlen( i8* %to ) nounwind readonly
       ; <i64> [#uses=1]
        %tmp18 = tail call i64 @strlen( i8* %from ) nounwind readonly
         ; <i64> [#uses=1]
        %tmp19 = add i64 %tmp16, 2 ; <i64> [#uses=1]
        %tmp20 = add i64 %tmp19, %tmp18 ; <i64> [#uses=1]
        %tmp21 = tail call i8* @alloca( i64 %tmp20 ) nounwind
; <i8*> [#uses=5]

other allocas in that file become instructions.

Andrew

Interestingly, in the .i file there are 2 __builtin_alloca, and
EmitBuiltinAlloca is only being called once.

Andrew

Andrew Lenharth wrote:

Interestingly, in the .i file there are 2 __builtin_alloca, and
EmitBuiltinAlloca is only being called once.

Hmm, here EmitBuiltinAlloca gets called twice, but it looks like
validate_arglist is rejecting the args both times.

I have 2 calls to alloca generated:
$ grep alloca x.bc|grep call
        %tmp21 = call i8* @alloca( i64 %tmp20 ) nounwind
; <i8*> [#uses=1]
        %tmp3 = call i8* @alloca( i64 %tmp2 ) nounwind ; <i8*>
[#uses=1]

I added some printfs around that code, running cc1 shows it never
reaches the 2nd printf:
4762│ printf("HERE!!\n");
4763│ tree arglist = TREE_OPERAND(exp, 1);
4764├> if (!validate_arglist(arglist, INTEGER_TYPE, VOID_TYPE))
4765│ return false;
4766│ printf("THERE!!\n")

Is there a way to nicely dump arglist?
gdb's print *arglist shows too much information....

$ /home/edwin/llvm-svn/obj42/./prev-gcc/cc1 charset.i
vprintf getchar fgetc_unlocked getc_unlocked getchar_unlocked putchar
fputc_unlocked putc_unlocked putchar_unlocked feof_unlocked
ferror_unlocked gnu_dev_major gnu_dev_minor gnu_dev_makedev atof atoi
atol atoll stat lstat fstat mknod cpp_in_system_header ustrcmp ustrncmp
ustrcspn ustrlen uxstrdup ustrchr ufputs one_utf8_to_cppchar
one_cppchar_to_utf8 one_utf8_to_utf32 one_utf32_to_utf8
one_utf8_to_utf16 one_utf16_to_utf8 conversion_loop convert_utf8_utf16
convert_utf8_utf32 convert_utf16_utf8 convert_utf32_utf8
convert_no_conversion convert_using_iconv init_iconv_descHERE!!
cpp_init_iconv _cpp_destroy_iconv cpp_host_to_exec_charset
width_to_mask ucn_valid_in_identifier _cpp_valid_ucn convert_ucn
emit_numeric_escape convert_hex convert_oct convert_escape
cpp_interpret_string cpp_interpret_string_notranslate
narrow_str_to_charconst wide_str_to_charconst cpp_interpret_charconst
_cpp_interpret_identifierHERE!!
_cpp_convert_input _cpp_default_encoding cpp_utf8_utf16
Execution times (seconds)
preprocessing : 0.02 ( 6%) usr 0.01 ( 6%) sys 0.04 ( 8%)
wall 285 kB ( 6%) ggc
lexical analysis : 0.01 ( 3%) usr 0.10 (59%) sys 0.08 (16%)
wall 0 kB ( 0%) ggc
parser : 0.06 (19%) usr 0.04 (24%) sys 0.13 (26%)
wall 2756 kB (56%) ggc
tree gimplify : 0.01 ( 3%) usr 0.00 ( 0%) sys 0.02 ( 4%)
wall 424 kB ( 9%) ggc
llvm backend functions: 0.03 ( 9%) usr 0.00 ( 0%) sys 0.03 ( 6%)
wall 1 kB ( 0%) ggc
llvm backend globals : 0.01 ( 3%) usr 0.00 ( 0%) sys 0.01 ( 2%)
wall 0 kB ( 0%) ggc
llvm backend per file : 0.17 (53%) usr 0.01 ( 6%) sys 0.18 (36%)
wall 0 kB ( 0%) ggc
TOTAL : 0.32 0.17 0.50 4953 kB

Best regards,
--Edwin

See the bug for a reduction and the gimple trees. validate_arglist
definately is rejecting the arglist in EmitBuiltinAlloca.

(try:
bool TreeToLLVM::EmitBuiltinAlloca(tree exp, Value *&Result) {
  tree arglist = TREE_OPERAND(exp, 1);
  if (!validate_arglist(arglist, INTEGER_TYPE, VOID_TYPE)) {
    debug_tree(arglist);
    return false;
  }
  Value *Amt = Emit(TREE_VALUE(arglist), 0);
  Amt = CastToSIntType(Amt, Type::Int32Ty);
  Result = Builder.CreateAlloca(Type::Int8Ty, Amt, "tmp");
  return true;
}
for a pretty (?) print of the tree at that point)

Andrew

Andrew Lenharth wrote:

See the bug for a reduction and the gimple trees. validate_arglist
definately is rejecting the arglist in EmitBuiltinAlloca.

(try:
bool TreeToLLVM::EmitBuiltinAlloca(tree exp, Value *&Result) {
  tree arglist = TREE_OPERAND(exp, 1);
  if (!validate_arglist(arglist, INTEGER_TYPE, VOID_TYPE)) {
    debug_tree(arglist);
    return false;
  }
  Value *Amt = Emit(TREE_VALUE(arglist), 0);
  Amt = CastToSIntType(Amt, Type::Int32Ty);
  Result = Builder.CreateAlloca(Type::Int8Ty, Amt, "tmp");
  return true;
}
for a pretty (?) print of the tree at that point)

Thanks, I am seeing a similar tree too. (with an extra pointertype
instead of void).

Best regards,
--Edwin

This is very strange. I built a cross compiler to x86_64-unknown-linux-gnu and it seems to work for me:

./cc1 /Users/sabre/pr1711.c -emit-llvm -quiet -O2 -o -

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"
target triple = "x86_64-unknown-linux-gnu"
  %struct.cpp_reader = type opaque

define i32 @_cpp_interpret_identifier(%struct.cpp_reader* %pfile, i8* %id, i64 %len) nounwind {
entry:
  ret i32 undef
}

-Chris

This is what I get with the non-bootstrap version.

Andrew

Ahh, ok. Somehow I didn't understand that this only happens when bootstrapping. It appears that the front-end builds file with --disable-bootstrap.

In this case, I can guess what is going on. This is probably due to the fact that llvm does not currently obey the X86-64 abi in some cases, particularly with respect to struct return. When bootstrapping, the C++ parts of the front-end are built with the native gcc compiler and the c parts are built with the bootstrapped C++ compiler. We're planning to fix the x86-64 abi issues (or make them much closer) for llvm 2.3, so I guess we'll have to wait for this (it's a big project).

Until then, using --disable-bootstrap is a reasonable workaround. Thanks for the help everyone!

-Chris