From f34312c23cde2f7cb65ad7e7a7e996278d4d1566 Mon Sep 17 00:00:00 2001 From: Carlos O'Donell Date: Mon, 30 Jan 2006 19:58:57 +0000 Subject: [PATCH] optabs.c (prepare_cmp_insn): If unbaised and unsigned then bias the comparison routine return. gcc/ 2006-01-30 Carlos O'Donell * optabs.c (prepare_cmp_insn): If unbaised and unsigned then bias the comparison routine return. gcc/testsuite/ 2006-01-30 Carlos O'Donell * gcc.dg/unsigned-long-compare.c: New test. From-SVN: r110409 --- gcc/ChangeLog | 5 ++++ gcc/optabs.c | 24 ++++++++++++-------- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/unsigned-long-compare.c | 24 ++++++++++++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/unsigned-long-compare.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8209ec63979..ede7d94ca6b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2006-01-30 Carlos O'Donell + + * optabs.c (prepare_cmp_insn): If unbaised and unsigned then bias + the comparison routine return. + 2006-01-30 Michael Matz * global.c (find_reg): Only evict for global regs. diff --git a/gcc/optabs.c b/gcc/optabs.c index 48a3406dc6b..bdbb88cce33 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3711,18 +3711,24 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK, word_mode, 2, x, mode, y, mode); + /* There are two kinds of comparison routines. Biased routines + return 0/1/2, and unbiased routines return -1/0/1. Other parts + of gcc expect that the comparison operation is equivalent + to the modified comparison. For signed comparisons compare the + result against 1 in the biased case, and zero in the unbiased + case. For unsigned comparisons always compare against 1 after + biasing the unbased result by adding 1. This gives us a way to + represent LTU. */ *px = result; *pmode = word_mode; - if (TARGET_LIB_INT_CMP_BIASED) - /* Integer comparison returns a result that must be compared - against 1, so that even if we do an unsigned compare - afterward, there is still a value that can represent the - result "less than". */ - *py = const1_rtx; - else + *py = const1_rtx; + + if (!TARGET_LIB_INT_CMP_BIASED) { - *py = const0_rtx; - *punsignedp = 1; + if (*punsignedp) + *px = plus_constant (result, 1); + else + *py = const0_rtx; } return; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3a6d317aad7..1aea281d1cc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2006-01-30 Carlos O'Donell + + * gcc.dg/unsigned-long-compare.c: New test. + 2006-01-30 Steve Ellcey PR testsuite/25318 diff --git a/gcc/testsuite/gcc.dg/unsigned-long-compare.c b/gcc/testsuite/gcc.dg/unsigned-long-compare.c new file mode 100644 index 00000000000..1c5c69cf038 --- /dev/null +++ b/gcc/testsuite/gcc.dg/unsigned-long-compare.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. */ +/* Contributed by Carlos O'Donell on 2006-01-30 */ + +/* Test a division corner case where the expression simplifies + to a comparison, and the optab expansion is wrong. The optab + expansion emits a function whose return is unbiased and needs + adjustment. */ +/* Origin: Carlos O'Donell */ +/* { dg-do run { target arm-*-*eabi* } } */ +/* { dg-options "" } */ +#include + +#define BIG_CONSTANT 0xFFFFFFFF80000000ULL + +int main (void) +{ + unsigned long long OneULL = 1ULL; + unsigned long long result; + + result = OneULL / BIG_CONSTANT; + if (result) + abort (); + exit (0); +}