Deutsch   English   Français   Italiano  
<vbsoro$3ol1a$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: BGB <cr88192@gmail.com>
Newsgroups: comp.arch
Subject: Re: Computer architects leaving Intel...
Date: Wed, 11 Sep 2024 13:51:26 -0500
Organization: A noiseless patient Spider
Lines: 155
Message-ID: <vbsoro$3ol1a$1@dont-email.me>
References: <vaqgtl$3526$1@dont-email.me>
 <memo.20240830090549.19028u@jgd.cix.co.uk>
 <2024Aug30.161204@mips.complang.tuwien.ac.at> <86r09ulqyp.fsf@linuxsc.com>
 <2024Sep8.173639@mips.complang.tuwien.ac.at>
 <p1cvdjpqjg65e6e3rtt4ua6hgm79cdfm2n@4ax.com>
 <2024Sep10.101932@mips.complang.tuwien.ac.at> <ygn8qvztf16.fsf@y.z>
 <2024Sep11.123824@mips.complang.tuwien.ac.at>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 11 Sep 2024 20:51:37 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="6f354a250eb5df0f06547a322cb410f4";
	logging-data="3953706"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX19fbkeGt5hq40BL21DKBc0OSghN7i/dZMk="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:4HyQEpaDhYzAfkk1v+ahu+94KvA=
In-Reply-To: <2024Sep11.123824@mips.complang.tuwien.ac.at>
Content-Language: en-US
Bytes: 6894

On 9/11/2024 5:38 AM, Anton Ertl wrote:
> Josh Vanderhoof <x@y.z> writes:
>> anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>>
>>> George Neuner <gneuner2@comcast.net> writes:
>>>> On Sun, 08 Sep 2024 15:36:39 GMT, anton@mips.complang.tuwien.ac.at
>>>> (Anton Ertl) wrote:
>>>>> 1) At first I thought that yes, one could just check whether there is
>>>>> an overlap of the memory areas.  But then I remembered that you cannot
>>>>> write such a check in standard C without (in the general case)
>>>>> exercising undefined behaviour; and then the compiler could eliminate
>>>>> the check or do something else that's unexpected.  Do you have such a
>>>>> check in mind that does not exercise undefined behaviour in the
>>>>> general case?
> ...
>> It is legal to test for equality between pointers to different objects
>> so you could test for overlap by testing against every element in the
>> array.  It seems like it should be possible for the compiler to figure
>> out what's happening and optimize those tests away, but unfortunately
>> no compiler I tested did it.
> 
> That would be an interesting result of the ATUBDNH lunacy: programmers
> would see themselves forced to write workarounds such as the one you
> suggest (with terrible performance when not optimized), and then C
> compiler maintainers would see themselves forced to optimize this kind
> of code.  The end result would be that both parties have to put in
> more effort to eventually get the same result as if ordered comparison
> between different objects had been defined from the start.
> 
> For now, the ATUBDNH advocates tell programmers that they have to work
> around the lack of definition, but there is usually no optimization
> for that.
> 
> One case where things work somewhat along the lines you suggest is
> unaligned accesses.  Traditionally, if knowing that the hardware
> supports unaligned accesses, for a 16-bit load one would write:
> 
> int16_t foo1(int16_t *p)
> {
>    return *p;
> }
> 
> If one does not know that the hardware supports unaligned accesses,
> the traditional way to perform such an access (little-endian) is
> something like:
> 
> int16_t foo2(int16_t *p)
> {
>    unsignedchar *q = p;
>    return (int16_t)(q[0] + (q[1]>>8));
> }
> 
> Now, several years ago, somebody told me that the proper way is as
> follows:
> 
> int16_t foo3(int16_t *p)
> {
>     int16_t v;
>     memcpy(&v,p,2);
>     return v;
> }
> 
> That way looked horribly inefficient to me, with v having to reside in
> memory instead of in a register and then the expensive function call,
> and all the decisions that memcpy() has to take depending on the
> length argument.  But gcc optimizes this idiom into an unaligned load
> rather than taking all the steps that I expected (however, I have seen
> cases where the code produced on hardware that supports unaligned
> accesses is worse than that for foo1()).  Of course, if you also want
> to support less sophisticated compilers, this idiom may be really slow
> on those, although not quite as expensive as your containment check.
> 

Would be nice, say, if there were semi-standard compiler macros for 
various things:
   Endianess (macros exist, typically compiler specific);
     And, apparently GCC and Clang can't agree on which strategy to use.
   Whether or not the target/compiler allows misaligned memory access;
     If set, one may use misaligned access.
   Whether or not memory uses a single address space;
     If set, all pointer comparisons are allowed.


Clang:
   __LITTLE_ENDIAN__, __BIG_ENDIAN__
   One or the other is defined based on endian.
GCC:
   __BYTE_ORDER__ which may equal one of:
     __ORDER_LITTLE_ENDIAN__
     __ORDER_BIG_ENDIAN__
     __ORDER_PDP_ENDIAN__
MSVC:
   REG_DWORD is one of:
     REG_DWORD_LITTLE_ENDIAN
     REG_DWORD_BIG_ENDIAN

GCC:
   __SIZEOF_type__  //gives sizeof various types


Possible:
   __MINALIGN_type__  //minimum allowed alignment for type

Where, if __MINALIGN_type__ is 1, this type may be freely unaligned in 
pointer accesses, otherwise specifying the minimum allowed alignment for 
accessing the type via a dereference. If 1, it also implies the ability 
to freely cast and dereference pointers of the given type.

Type may cover both named types (short/int/long) and fixed types 
(int32/int64).

#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__)
#if defined(__MINALIGN_INT32__) && (__MINALIGN_INT32__==1)
#define GET_INT32LE(ptr) (*(int32_t *)(ptr))
#else
int32_t GET_INT32LE(void *ptr)
{
   int32_t v;
   memcpy(&v, ptr, 4);
   return(v);
}
#endif
#else
int32_t GET_INT32LE(void *ptr)
{
   uint8_t *p;
   int32_t v;
   p=ptr;
   v=p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
   return(v);
}
#endif



Maybe also alias pointer control:
   __POINTER_ALIAS__
     __POINTER_ALIAS_CONSERVATIVE__
     __POINTER_ALIAS_STRICT__

Where, pointer alias can be declared, and:
   If conservative, then conservative semantics are being used.
     Pointers may be freely cast without concern for pointer aliasing.
     Compiler will assume that "non restrict" pointer stores may alias.
   If strict, the compiler is using TBAA semantics.
     Compiler may assume that aliasing is based on pointer types.

So, say:
   #if defined(__POINTER_ALIAS__) && \
     (__POINTER_ALIAS__==__POINTER_ALIAS_CONSERVATIVE__)
   //we are free to cast stuff however we want here...
   #endif

> - anton