unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* `SCM_MAKE_CHAR ()' signedness issue
@ 2009-08-15 12:00 Ludovic Courtès
  2009-08-16 21:58 ` Ken Raeburn
  0 siblings, 1 reply; 13+ messages in thread
From: Ludovic Courtès @ 2009-08-15 12:00 UTC (permalink / raw)
  To: guile-devel

Hello,

We still have troubles with the `(scm_t_int32) (x) < 0' test in
`SCM_MAKE_CHAR ()':

--8<---------------cut here---------------start------------->8---
ludo@gcc54:~/guile-1.9.1/+build$ cat ,,t.c
int
foo (unsigned char x)
{
  return (((int)x) < 0 ? 1 : -1);
}
ludo@gcc54:~/guile-1.9.1/+build$ gcc -Wall -c ,,t.c
,,t.c: In function ‘foo’:
,,t.c:4: warning: comparison is always false due to limited range of data type
ludo@gcc54:~/guile-1.9.1/+build$ ../build-aux/config.guess 
sparc64-unknown-linux-gnu
ludo@gcc54:~/guile-1.9.1/+build$ gcc --version
gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
--8<---------------cut here---------------end--------------->8---

The problem occurs, e.g., in `string_titlecase_x ()'.

Surprisingly, GCC 4.4 on x86_64-linux-gnu doesn't yield any warning for
the example above.

I'm not sure how to fix it, so we'll see for the next release.

Thanks,
Ludo'.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-15 12:00 `SCM_MAKE_CHAR ()' signedness issue Ludovic Courtès
@ 2009-08-16 21:58 ` Ken Raeburn
  2009-08-16 22:13   ` Ludovic Courtès
  0 siblings, 1 reply; 13+ messages in thread
From: Ken Raeburn @ 2009-08-16 21:58 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guile-devel

On Aug 15, 2009, at 08:00, Ludovic Courtès wrote:
> Hello,
>
> We still have troubles with the `(scm_t_int32) (x) < 0' test in
> `SCM_MAKE_CHAR ()':
>
> --8<---------------cut here---------------start------------->8---
> ludo@gcc54:~/guile-1.9.1/+build$ cat ,,t.c
> int
> foo (unsigned char x)
> {
>  return (((int)x) < 0 ? 1 : -1);
> }
> ludo@gcc54:~/guile-1.9.1/+build$ gcc -Wall -c ,,t.c
> ,,t.c: In function ‘foo’:
> ,,t.c:4: warning: comparison is always false due to limited range of  
> data type

In the case of SCM_MAKE_CHAR, both actions give identical results for  
an input of 0, so I think just testing "x <= 0" will silence the  
warning without changing the behavior.

There's always the inline-function approach, too.

Ken



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-16 21:58 ` Ken Raeburn
@ 2009-08-16 22:13   ` Ludovic Courtès
  2009-08-16 22:25     ` Ken Raeburn
  0 siblings, 1 reply; 13+ messages in thread
From: Ludovic Courtès @ 2009-08-16 22:13 UTC (permalink / raw)
  To: guile-devel

Ken Raeburn <raeburn@raeburn.org> writes:

> In the case of SCM_MAKE_CHAR, both actions give identical results for
> an input of 0, so I think just testing "x <= 0" will silence the
> warning without changing the behavior.

Oh, good point.

> There's always the inline-function approach, too.

Unfortunately no, because we're still not assuming `inline' keyword
support from the compiler.

Thanks,
Ludo'.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-16 22:13   ` Ludovic Courtès
@ 2009-08-16 22:25     ` Ken Raeburn
  2009-08-17  8:26       ` Ludovic Courtès
  0 siblings, 1 reply; 13+ messages in thread
From: Ken Raeburn @ 2009-08-16 22:25 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guile-devel

On Aug 16, 2009, at 18:13, Ludovic Courtès wrote:
>> There's always the inline-function approach, too.
>
> Unfortunately no, because we're still not assuming `inline' keyword
> support from the compiler.

Right, but inline.h deals with that; if "inline" isn't supported you  
just get a declaration and make a function call.  There would be a  
performance hit from doing the function calls all the time, but I  
think it would work.  In fact, there are cases where the argument to  
SCM_MAKE_CHAR is a function invocation, where it might be beneficial  
for performance to not compute the value twice.

Ken



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-16 22:25     ` Ken Raeburn
@ 2009-08-17  8:26       ` Ludovic Courtès
  2009-08-17 13:05         ` Mike Gran
  0 siblings, 1 reply; 13+ messages in thread
From: Ludovic Courtès @ 2009-08-17  8:26 UTC (permalink / raw)
  To: guile-devel

Hi,

Ken Raeburn <raeburn@raeburn.org> writes:

> On Aug 16, 2009, at 18:13, Ludovic Courtès wrote:
>>> There's always the inline-function approach, too.
>>
>> Unfortunately no, because we're still not assuming `inline' keyword
>> support from the compiler.
>
> Right, but inline.h deals with that; if "inline" isn't supported you
> just get a declaration and make a function call.  There would be a
> performance hit from doing the function calls all the time,

Yes, I'm not sure that's something worth trying.

> In fact, there are cases where the argument to SCM_MAKE_CHAR is a
> function invocation, where it might be beneficial for performance to
> not compute the value twice.

Right, but I guess these could be avoided trivially.

Thanks,
Ludo'.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-17  8:26       ` Ludovic Courtès
@ 2009-08-17 13:05         ` Mike Gran
  2009-08-17 15:33           ` Ludovic Courtès
  0 siblings, 1 reply; 13+ messages in thread
From: Mike Gran @ 2009-08-17 13:05 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guile-devel

Hi-

On Mon, 2009-08-17 at 10:26 +0200, Ludovic Courtès wrote: 
> Hi,
> 
> Ken Raeburn <raeburn@raeburn.org> writes:
> 
> > On Aug 16, 2009, at 18:13, Ludovic Courtès wrote:
> >>> There's always the inline-function approach, too.
> >>
> >> Unfortunately no, because we're still not assuming `inline' keyword
> >> support from the compiler.
> >
> > Right, but inline.h deals with that; if "inline" isn't supported you
> > just get a declaration and make a function call.  There would be a
> > performance hit from doing the function calls all the time,
> 
> Yes, I'm not sure that's something worth trying.

On my system I ran a test with SCM_MAKE_CHAR as a macro, an an inline,
and as a never inlined function.  I ran ./check-guile twice for each.

SCM_MAKE_CHAR as macro, ./check-guile gives
real 0m22.680s 0m22.658s
user 0m7.700s  0m7.640s
sys 0m1.067s  0m1.124s

SCM scm_i_make_char (scm_t_int32 x) __attribute__((noinline))
real 0m22.010s 0m21.998s
user 0m7.631s  0m7.648s
sys 0m1.151s  0m1.076s

SCM inline scm_i_make_char (scm_t_int32 x)
real 0m22.107s 0m21.914s
user 0m7.614s  0m7.726s
sys 0m1.115s  0m1.068s

The timing differences between them seem to be in the noise, for this
one test.

Thanks,

Mike





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-17 13:05         ` Mike Gran
@ 2009-08-17 15:33           ` Ludovic Courtès
  2009-08-18 17:32             ` Mike Gran
  0 siblings, 1 reply; 13+ messages in thread
From: Ludovic Courtès @ 2009-08-17 15:33 UTC (permalink / raw)
  To: guile-devel

Mike Gran <spk121@yahoo.com> writes:

> On my system I ran a test with SCM_MAKE_CHAR as a macro, an an inline,
> and as a never inlined function.  I ran ./check-guile twice for each.

You're cheating!  ;-)

The test suite does lots of things besides calling `SCM_MAKE_CHAR ()',
so I'm not sure if it's a good benchmark.

I'm fairly confident that for such a small piece of code inlining is
always a good idea.

Thanks,
Ludo'.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
@ 2009-08-17 18:52 carlo.bramix
  2009-08-17 19:41 ` Ken Raeburn
  0 siblings, 1 reply; 13+ messages in thread
From: carlo.bramix @ 2009-08-17 18:52 UTC (permalink / raw)
  To: guile-devel

Hello,
if I understood the problem, I think it can be easily fixed without using an inline function.

For example:

#ifdef __GNUC__

#define SCM_MAKE_CHAR(__x)                                            \
({ scm_t_int32 __t = (scm_t_int32)(__x);                              \
  (__t < 0)                                                           \
  ? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (__x), scm_tc8_char) \
  : SCM_MAKE_ITAG8 ((scm_t_bits) (__x), scm_tc8_char);                \
  __t;                                                                \
})

#else

#define SCM_MAKE_CHAR(x)                                              \
  ((scm_t_int32) (x) < 0                                              \
  ? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char)   \
  : SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char))

#endif

solves the problem.
Actually a much more efficient solution specifically designed for GCC may use __builtin_types_compatible_p() and __builtin_choose_expr() intrinsic functions, but this will force you to support GCC 3.x or newer.

Something like:
#if defined __GNUC__ && __GNUC__ >= 3
...
#elif ...

will need to be written.

Sincerely,

Carlo Bramini.

---------- Initial Header -----------

From      : guile-devel-bounces+carlo.bramix=libero.it@gnu.org
To          : guile-devel@gnu.org
Cc          :
Date      : Mon, 17 Aug 2009 17:33:03 +0200
Subject : Re: `SCM_MAKE_CHAR ()' signedness issue

> Mike Gran <spk121@yahoo.com> writes:
>
> > On my system I ran a test with SCM_MAKE_CHAR as a macro, an an inline,
> > and as a never inlined function.  I ran ./check-guile twice for each.
>
> You're cheating!  ;-)
>
> The test suite does lots of things besides calling `SCM_MAKE_CHAR ()',
> so I'm not sure if it's a good benchmark.
>
> I'm fairly confident that for such a small piece of code inlining is
> always a good idea.
>
> Thanks,
> Ludo'.
>






^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-17 18:52 carlo.bramix
@ 2009-08-17 19:41 ` Ken Raeburn
  0 siblings, 0 replies; 13+ messages in thread
From: Ken Raeburn @ 2009-08-17 19:41 UTC (permalink / raw)
  To: carlo.bramix; +Cc: guile-devel

On Aug 17, 2009, at 14:52, carlo.bramix wrote:
> Hello,
> if I understood the problem, I think it can be easily fixed without  
> using an inline function.
>
> For example:
>
> #ifdef __GNUC__

Relying on GCC-specific syntax is probably worse than an inline  
function.  Part of Ludovic's complaint was that we don't want to  
depend on "inline" working in some random compiler; but then, we  
certainly shouldn't depend on statement expressions working everywhere  
either.  And if you're going to conditionalize GCC and non-GCC  
versions, you might as well use an inline function in the GCC case,  
especially since other C99 compilers should support it as well.  The  
machinery in inline.h is set up to deal with that, though it chooses  
between inline expansion and function calls, not between inline  
function expansion and macro expansion.  I think we can probably argue  
that if inline function expansion is disabled for some reason in a  
compiler that does support it, performance is not a key issue;  
probably "-O" was omitted on the command line or something.  So the  
thought of falling back to a function call in that case really doesn't  
bother me.

(I have written code to rely on GCC-specific extensions before, and  
code that conditionalizes such things. I think there are cases where  
you may want to do that.  I just don't think this is one of them.)

The only benefits I see here to going with the macro are (1) minor  
performance differences on non-C99, non-GCC compilers, (2) different  
semantics if some odd type -- like a 64-bit value -- is provided, (3)  
simpler code, if you just have one version of the macro.

Ken




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-17 15:33           ` Ludovic Courtès
@ 2009-08-18 17:32             ` Mike Gran
  0 siblings, 0 replies; 13+ messages in thread
From: Mike Gran @ 2009-08-18 17:32 UTC (permalink / raw)
  To: Ludovic Courtès, guile-devel

> From: Ludovic Courtès <ludo@gnu.org>
> To: guile-devel@gnu.org
> Sent: Monday, August 17, 2009 8:33:03 AM
> Subject: Re: `SCM_MAKE_CHAR ()' signedness issue
> 
> I'm fairly confident that for such a small piece of code inlining is
> always a good idea.

OK.  If the comparison is modified to become

35 #define SCM_MAKE_CHAR(x)                                               \
36   (((x) < 128)                                               \
37    ? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char)   \
38    : SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char))

Then hopefully that will solve all the build problems.

> Thanks,
> Ludo'.

-Mike





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
@ 2009-08-18 18:39 carlo.bramix
  2009-08-18 18:54 ` Mike Gran
  0 siblings, 1 reply; 13+ messages in thread
From: carlo.bramix @ 2009-08-18 18:39 UTC (permalink / raw)
  To: guile-devel

Hello,
unfortunately that code still fails into libguile/print.c
Infact, a signed char just arrives to 127 and the " < 128" causes:

../../guile-git/libguile/print.c:1101: warning: comparison is always true due to limited range of data type
../../guile-git/libguile/print.c:1108: warning: comparison is always true due to limited range of data type

But in this manner it seems ok:

#define SCM_MAKE_CHAR(x)                                               \
  (((scm_t_int32) (x) + 128) < 128                                     \
   ? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char)   \
   : SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char))

Sincerely,

Carlo Bramini.

---------- Initial Header -----------

From      : guile-devel-bounces+carlo.bramix=libero.it@gnu.org
To          : "Ludovic Courtès" ludo@gnu.org, guile-devel@gnu.org
Cc          :
Date      : Tue, 18 Aug 2009 10:32:29 -0700 (PDT)
Subject : Re: `SCM_MAKE_CHAR ()' signedness issue

> > From: Ludovic Courtès <ludo@gnu.org>
> > To: guile-devel@gnu.org
> > Sent: Monday, August 17, 2009 8:33:03 AM
> > Subject: Re: `SCM_MAKE_CHAR ()' signedness issue
> >
> > I'm fairly confident that for such a small piece of code inlining is
> > always a good idea.
>
> OK.  If the comparison is modified to become
>
> 35 #define SCM_MAKE_CHAR(x)                                               \
> 36   (((x) < 128)                                               \
> 37    ? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char)   \
> 38    : SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char))
>
> Then hopefully that will solve all the build problems.
>
> > Thanks,
> > Ludo'.
>
> -Mike
>
>
>
>





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-18 18:39 carlo.bramix
@ 2009-08-18 18:54 ` Mike Gran
  2009-08-18 23:36   ` Greg Troxel
  0 siblings, 1 reply; 13+ messages in thread
From: Mike Gran @ 2009-08-18 18:54 UTC (permalink / raw)
  To: carlo.bramix, guile-devel

> From: carlo.bramix <carlo.bramix@libero.it>
> 
> Hello,
> unfortunately that code still fails into libguile/print.c
> Infact, a signed char just arrives to 127 and the " < 128" causes:
> 
> ../../guile-git/libguile/print.c:1101: warning: comparison is always true due to 
> limited range of data type
> ../../guile-git/libguile/print.c:1108: warning: comparison is always true due to 
> limited range of data type

Doh!  You're right.

> 
> But in this manner it seems ok:
> 
> #define SCM_MAKE_CHAR(x)                                              \
>   (((scm_t_int32) (x) + 128) < 128                                    \
>   ? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char)  \
>   : SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char))

Alternately, you could put in any number between 0 and 127, I think, and get 
the correct behavior.

#define SCM_MAKE_CHAR(x)                                              \
  ((x) < 64                                    \
  ? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char)  \
  : SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char))

-Mike





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: `SCM_MAKE_CHAR ()' signedness issue
  2009-08-18 18:54 ` Mike Gran
@ 2009-08-18 23:36   ` Greg Troxel
  0 siblings, 0 replies; 13+ messages in thread
From: Greg Troxel @ 2009-08-18 23:36 UTC (permalink / raw)
  To: Mike Gran; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 342 bytes --]


I think the problem is that the routine in question is fundamentally
written to assume a signed input.  Perhaps there should be an unsigned
version that takes unsigned chars, and perhaps guile should explicit
declare characters as one or the other.  Or perhaps just always cast to
unsigned char - if it is already unsiged that is a no-op.



[-- Attachment #2: Type: application/pgp-signature, Size: 193 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-08-18 23:36 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-15 12:00 `SCM_MAKE_CHAR ()' signedness issue Ludovic Courtès
2009-08-16 21:58 ` Ken Raeburn
2009-08-16 22:13   ` Ludovic Courtès
2009-08-16 22:25     ` Ken Raeburn
2009-08-17  8:26       ` Ludovic Courtès
2009-08-17 13:05         ` Mike Gran
2009-08-17 15:33           ` Ludovic Courtès
2009-08-18 17:32             ` Mike Gran
  -- strict thread matches above, loose matches on Subject: below --
2009-08-17 18:52 carlo.bramix
2009-08-17 19:41 ` Ken Raeburn
2009-08-18 18:39 carlo.bramix
2009-08-18 18:54 ` Mike Gran
2009-08-18 23:36   ` Greg Troxel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).