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.
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.
When I looked at this, the libcall was eliminated in the call to delete_trivially_dead_insns, somewhere around jump1.
*** Bug 25418 has been marked as a duplicate of this bug. ***
*** Bug 27261 has been marked as a duplicate of this bug. ***
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.
*** Bug 32153 has been marked as a duplicate of this bug. ***
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); }
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.
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.
Doesn't help.
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?
*** Bug 36398 has been marked as a duplicate of this bug. ***
*** Bug 36868 has been marked as a duplicate of this bug. ***
libcalls are gone in 4.4 and later.
I'm not sure if this bug is fixed, though. -ftrapv is still broken afaik.
> 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.
*** 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.