Bug 19020 - libcalls are removed (-ftrapv does not work)
libcalls are removed (-ftrapv does not work)
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: middle-end
4.0.0
: P2 normal
: 4.4.0
Assigned To: Not yet assigned to anyone
: wrong-code
: 25418 27261 32153 36398 36868 (view as bug list)
Depends on:
Blocks: 35412 35413
  Show dependency treegraph
 
Reported: 2004-12-15 20:23 UTC by Eric Botcazou
Modified: 2014-02-16 13:16 UTC (History)
12 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-11-13 16:50:18


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Botcazou 2004-12-15 20:23:38 UTC
The following code should abort at runtime when compiled with -ftrapv:

#include <limits.h>

int __attribute__((noinline))
iaddv (int a, int b)
{
  return a + b;
}

int main(void)
{
  iaddv (INT_MAX, 1);
  return 0;
}

It doesn't in 64-bit mode:
[eric@localhost native]$ gcc-4.0 -o addv addv.c -ftrapv
[eric@localhost native]$ ./addv
[eric@localhost native]$ gcc-4.0 -o addv addv.c -ftrapv -m32
[eric@localhost native]$ ./addv
Aborted

The problem originates in .03.jump: the libcall to __addvdi3 is eliminated.
Comment 1 Steven Bosscher 2004-12-15 20:51:23 UTC
This doesn't happen on just amd64, I've seen this bug on all targets 
when I was playing with a patch to blow away libcall notes.  On ia64 
it lead to a link failure because of missing symbols, so fixing this 
problem will probably uncover a few latent bugs elsewhere. 
 
Comment 2 Steven Bosscher 2004-12-15 20:52:16 UTC
When I looked at this, the libcall was eliminated in the call to 
delete_trivially_dead_insns, somewhere around jump1. 
 
Comment 3 Andrew Pinski 2005-12-14 18:32:28 UTC
*** Bug 25418 has been marked as a duplicate of this bug. ***
Comment 4 Andrew Pinski 2006-04-22 15:41:04 UTC
*** Bug 27261 has been marked as a duplicate of this bug. ***
Comment 5 Richard Biener 2007-01-17 15:35:08 UTC
There are a few issues, first we use emit_libcall_block to emit the trapping PLUS
which sets a REG_EQUAL note with a non-trapping PLUS.

Second we analyze iaddv as not possibly throwing so we remove the call from main()
during tree optimization as the result is unused.

Third, we widen the integer addition to DImode and dispatch to libgcc2 __addvdi3
which looks like

Dump of assembler code for function __addvdi3:
0x0000000000400580 <__addvdi3+0>:       sub    $0x8,%rsp
0x0000000000400584 <__addvdi3+4>:       test   %rsi,%rsi
0x0000000000400587 <__addvdi3+7>:       lea    (%rdi,%rsi,1),%rax
0x000000000040058b <__addvdi3+11>:      js     0x4005a0 <__addvdi3+32>
0x000000000040058d <__addvdi3+13>:      cmp    %rax,%rdi

so it tests for 64bit overflow instead of 32bit one.  Obviously allowind
LIBCALL_WIDEN is wrong for the trapping optabs, too.
Comment 6 Richard Biener 2007-05-30 19:59:34 UTC
*** Bug 32153 has been marked as a duplicate of this bug. ***
Comment 7 Steven Bosscher 2008-03-01 10:50:34 UTC
With trunk as of today, the test case of comment #0 does trap if optimization is disabled. At -O, the libcall is optimized away, but the call to iaddv() from main() is also optimized away because iaddv is found to be pure.  You must use the result of iaddv() to avoid this:

#include <limits.h>

int __attribute__((noinline))
iaddv (int a, int b)
{
  return a + b;
}

int main(void)
{
  return iaddv (INT_MAX, 1);
}
Comment 8 Richard Biener 2008-03-01 13:52:32 UTC
On the expand side it is just wrong (and asking for trouble) to go the usual
expand_binop way for expanding trapping arithmetic.  At least we would need to
pass down a flag.
Comment 9 Richard Biener 2008-03-01 14:29:46 UTC
If you remove libcall notes around all binops then the following testcase passes in dg-torture:

/* { dg-do run { target hppa*-*-hpux* *-*-linux* powerpc*-*-darwin* *-*-darwin[912]* } } */
/* { dg-options "-ftrapv" } */

#include <stdlib.h>
#include <limits.h>
#include <signal.h>

int ok;

void handle_abort (int sig)
{
  if (sig == SIGABRT)
    {
      ok = 1;
      exit (0);
    }
}

int __attribute__((noinline))
iaddv (int a, int b)
{
  return a + b;
}

volatile int x;

int main(void)
{
  struct sigaction sa;
  sigemptyset (&sa.sa_mask);
  sa.sa_handler = handle_abort;
  sa.sa_flags = SA_RESETHAND;
  if (sigaction (SIGABRT, &sa, NULL) == -1)
    return 0;
  /* ???  iaddv is analyzed to be pure, so use the result.  */
  x = iaddv (INT_MAX, 1);
  sa.sa_handler = SIG_DFL;
  if (sigaction (SIGABRT, &sa, NULL) == -1)
    return 0;
  if (!ok)
    abort ();
  return 0;
}

but I get a build failure of libjava then:

gnu/java/nio/natVMSelector.cc: In static member function 'static jint gnu::java::nio::VMSelector::select(JArray<__java_int>*, JArray<__java_int>*, JArray<__java_int>*, jlong)':
gnu/java/nio/natVMSelector.cc:127: error: unable to find a register to spill in class 'AD_REGS'
gnu/java/nio/natVMSelector.cc:127: error: this is the insn:
(insn 58 57 59 6 gnu/java/nio/natVMSelector.cc:82 (parallel [
            (set (reg:DI 4 si [165])
                (mult:DI (zero_extend:DI (reg:SI 0 ax))
                    (zero_extend:DI (reg:SI 2 cx [166]))))
            (clobber (reg:CC 17 flags))
        ]) 304 {*umulsidi3_insn} (expr_list:REG_DEAD (reg:SI 2 cx [166])
        (expr_list:REG_DEAD (reg:SI 0 ax)
            (expr_list:REG_UNUSED (reg:CC 17 flags)
                (expr_list:REG_EQUAL (mult:DI (zero_extend:DI (reg:SI 0 ax))
                        (const_int 1000 [0x3e8]))
                    (nil))))))
gnu/java/nio/natVMSelector.cc:127: internal compiler error: in spill_failure, at reload1.c:2000
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.


with the following patch

Index: optabs.c
===================================================================
--- optabs.c	(revision 132790)
+++ optabs.c	(working copy)
@@ -2148,12 +2148,9 @@ expand_binop (enum machine_mode mode, op
 
       insns = get_insns ();
       end_sequence ();
+      emit_insn (insns);
 
-      target = gen_reg_rtx (mode);
-      emit_libcall_block (insns, target, value,
-			  gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
-
-      return target;
+      return value;
     }
 
   delete_insns_since (last);


I'll test forcing value to a register.
Comment 10 Richard Biener 2008-03-01 15:24:01 UTC
Doesn't help.
Comment 11 Steven Bosscher 2008-03-03 19:35:53 UTC
Quoting your insn once more:

(insn 58 57 59 6 gnu/java/nio/natVMSelector.cc:82 (parallel [
            (set (reg:DI 4 si [165])
                (mult:DI (zero_extend:DI (reg:SI 0 ax))
                    (zero_extend:DI (reg:SI 2 cx [166]))))
            (clobber (reg:CC 17 flags))
        ]) 304 {*umulsidi3_insn} (expr_list:REG_DEAD (reg:SI 2 cx [166])
        (expr_list:REG_DEAD (reg:SI 0 ax)
            (expr_list:REG_UNUSED (reg:CC 17 flags)
                (expr_list:REG_EQUAL (mult:DI (zero_extend:DI (reg:SI 0 ax))
                        (const_int 1000 [0x3e8]))
                    (nil))))))

The register allocator failed to make your insn satisfy its constraints. Operand 0 is (reg:DI 4 si) but the constraint for it is "=A", i.e. the ax register.

The funny thing is that reload wants to make operand 0 be (reg:DI 0 ax), but somehow it can't, even though (reg:SI 0 ax) dies in this insn. So apparently the high part of (reg:DI 0 ax), i.e. (reg:SI 1 dx), lives across the insn.

This looks to me like a case of PR35404.  What do you think, Ian?
Comment 12 Paolo Bonzini 2008-05-31 07:25:26 UTC
*** Bug 36398 has been marked as a duplicate of this bug. ***
Comment 13 Richard Biener 2008-07-18 18:22:31 UTC
*** Bug 36868 has been marked as a duplicate of this bug. ***
Comment 14 Eric Botcazou 2008-11-29 22:19:57 UTC
libcalls are gone in 4.4 and later.
Comment 15 Steven Bosscher 2008-11-29 22:23:52 UTC
I'm not sure if this bug is fixed, though.  -ftrapv is still broken afaik.
Comment 16 Eric Botcazou 2008-11-29 22:29:04 UTC
> I'm not sure if this bug is fixed, though.  -ftrapv is still broken afaik.

Probably, but let's ditch antiquated stuff and start afresh.
Comment 17 Jackie Rosen 2014-02-16 13:16:27 UTC
*** Bug 260998 has been marked as a duplicate of this bug. ***
Seen from the domain http://volichat.com
Page where seen: http://volichat.com/adult-chat-rooms
Marked for reference. Resolved as fixed @bugzilla.