bagel99 / llvm-my66000

This is a fork of the LLVM project. The code in branch my66000 supports Mitch Alsup's MY66000. The code in branch mcore supports the Motorola MCore.
http://llvm.org
Other
2 stars 2 forks source link

Apparent endless loop in compilation of pr44942.c (va_args) #22

Closed tkoenig1 closed 1 year ago

tkoenig1 commented 1 year ago

The compilation of a gcc test case took > 19 minutes on my home box before I killed it. Here is the source:

/* PR target/44942 */

#include <stdarg.h>

void
test1 (int a, int b, int c, int d, int e, int f, int g, long double h, ...)
{
  int i;
  va_list ap;

  va_start (ap, h);
  i = va_arg (ap, int);
  if (i != 1234)
    __builtin_abort ();
  va_end (ap);
}

void
test2 (int a, int b, int c, int d, int e, int f, int g, long double h, int i,
       long double j, int k, long double l, int m, long double n, ...)
{
  int o;
  va_list ap;

  va_start (ap, n);
  o = va_arg (ap, int);
  if (o != 1234)
    __builtin_abort ();
  va_end (ap);
}

void
test3 (double a, double b, double c, double d, double e, double f,
       double g, long double h, ...)
{
  double i;
  va_list ap;

  va_start (ap, h);
  i = va_arg (ap, double);
  if (i != 1234.0)
    __builtin_abort ();
  va_end (ap);
}

void
test4 (double a, double b, double c, double d, double e, double f, double g,
       long double h, double i, long double j, double k, long double l,
       double m, long double n, ...)
{
  double o;
  va_list ap;

  va_start (ap, n);
  o = va_arg (ap, double);
  if (o != 1234.0)
    __builtin_abort ();
  va_end (ap);
}

int
main ()
{
  test1 (0, 0, 0, 0, 0, 0, 0, 0.0L, 1234);
  test2 (0, 0, 0, 0, 0, 0, 0, 0.0L, 0, 0.0L, 0, 0.0L, 0, 0.0L, 1234);
  test3 (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0L, 1234.0);
  test4 (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0L, 0.0, 0.0L,
         0.0, 0.0L, 0.0, 0.0L, 1234.0);
  return 0;
}

I have attached the *.bc file as well.

pr44942.zip

tkoenig1 commented 1 year ago

Seems to be a more general problem with varargs, I had to kill several other test cases as well.

tkoenig1 commented 1 year ago

Shorter test case:

#include <stdarg.h>

typedef double L;
void f (L p0, L p1, L p2, L p3, L p4, L p5, L p6, L p7, L p8, ...)
{
  va_list select;

  va_start (select, p8);

  if (va_arg (select, int) != 10)
    abort ();
  if (va_arg (select, int) != 11)
    abort ();
  if (va_arg (select, int) != 12)
    abort ();

  va_end (select);
}

int main ()
{
  f (1., 2., 3., 4., 5., 6., 7., 8., 9., 10, 11, 12);
  exit (0);
}
tkoenig1 commented 1 year ago

With the Debug version, the error message changes to

Too many var args parameters.
UNREACHABLE executed at /home/asdf/llvm-my66000/llvm/lib/Target/My66000/My66000ISelLowering.cpp:935!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
bagel99 commented 1 year ago

Try again with commit 4c3bbcf161cfd1940c03640c831d1e2b24ba783d

tkoenig1 commented 1 year ago

The internal compiler error is gone, but the code looks wrong. I don't have a simulator to test it on, but the simplified test case

/* PR target/44942 */

#include <stdarg.h>

void
test1 (int a, int b, int c, int d, int e, int f, int g, long double h, ...)
{
  int i;
  va_list ap;

  va_start (ap, h);
  i = va_arg (ap, int);
  if (i != 1234)
    __builtin_abort ();
  va_end (ap);
}

int
main ()
{
  test1 (0, 0, 0, 0, 0, 0, 0, 0.0L, 1234);
  return 0;
}

using the compile script

#! /bin/bash
a=${1%%.[ci]}
b=${a}_opt
clang -fomit-frame-pointer -fverbose-asm -c --target=my66000 -O3 -fno-vectorize -fno-slp-vectorize  -emit-llvm -fno-unroll-loops $1
opt  -disable-loop-unrolling -O3  --march=my66000 --frame-pointer=none --enable-vvm $a.bc  > $b.bc
llc --disable-lsr --enable-predication --enable-predication2 --enable-carry-generation --early-carry-coalesce --enable-vvm -march=my66000 $b.bc

results in the assembly code

test1:                                  ; @test1
; %bb.0:                                ; %entry
        add     sp,sp,#-16
        add     r1,sp,#0
        add     r1,r1,#8
        std     r1,[sp]
        and     r1,r1,#4294967292
        cmp     r1,r1,#1234
        bne     r1,.LBB0_1
; %bb.2:                                ; %if.end
        add     sp,sp,#16
        ret
.LBB0_1:                                ; %if.then
        call    abort
.Lfunc_end0:
        .size   test1, .Lfunc_end0-test1
                                        ; -- End function
        .globl  main                            ; -- Begin function main
        .type   main,@function
main:                                   ; @main
; %bb.0:                                ; %entry
        enter   r30,r0,0,8
        std     #1234,[sp]
        mov     r30,#0
        mov     r1,r30
        mov     r2,r30
        mov     r3,r30
        mov     r4,r30
        mov     r5,r30
        mov     r6,r30
        mov     r7,r30
        call    test1
        mov     r1,r30
        exit    r30,r0,0,8

Now, main stores the value 1234 on the stack, that looks OK. But what test1 is doing... it does not appear to load the value from the stack. Rather, it adds 8 to the stack value, stores it on the stack, masks it with 0xfffffffc and then compares it against 1234. That does not look right.

bagel99 commented 1 year ago

Yes, that code looks wrong I had tested against your "Shorter test case" and that code looked OK. Varargs is one of the least tested part of the compiler.

bagel99 commented 1 year ago

Try again with commit 5a26c794e6a7

tkoenig1 commented 1 year ago

OK, forget what I wrote in this comment a minute ago, the code indeed looks fine now. I was confused by the decimal constant.

tkoenig1 commented 1 year ago

So, looks fixed. Great!