integer promotion

J

James Kuyper

Using shift amounts 32 or greater on 32 bit int, and expecting
a specific result, caused OS/360 to fail.

That's permitted for a conforming compiler when translating code with
undefined behavior, as this is.
 
K

Keith Thompson

glen herrmannsfeldt said:
(snip on shift operations equal to or longer than the operand
being shifted, then I wrote)



Using shift amounts 32 or greater on 32 bit int, and expecting
a specific result, caused OS/360 to fail.

Is that intended to imply disagreement with my statement?

The behavior is undefined. Making demons fly out of OS/360's
nonexistent nose would be conforming behavior.

[...]
 
G

glen herrmannsfeldt

(snip, previously I wrote)
Is that intended to imply disagreement with my statement?
The behavior is undefined. Making demons fly out of OS/360's
nonexistent nose would be conforming behavior.

I wasn't sure what you meant by "wrong", but doing something
with undefined behavior, and expecting a specific behavior,
seems "wrong" to me.

-- glen
 
K

Keith Thompson

glen herrmannsfeldt said:
I wasn't sure what you meant by "wrong", but doing something
with undefined behavior, and expecting a specific behavior,
seems "wrong" to me.

Ok, I think we're in agreement.

A 32-bit shift on a 32-bit word behaves in some particular manner or
OS/360. That behavior is not "wrong", in that it doesn't imply the C
implementation is (was?) non-conforming. Any code that depends on any
particular behavior is "wrong" in the sense that its behavior is
undefined.

If you were saying that the behavior of the Hercules S/360 emulator
differed from the behavior of an actual S/360, I'll take your word for
it (and it's not a C conformance issue).
 
J

James Kuyper

(snip, previously I wrote)



I wasn't sure what you meant by "wrong", ...

The word "wrong" entered this discussion through your comments "I
noticed that they had this wrong", and "Using the C shift operators on
32 bit words got this wrong", so the key question is what "wrong" meant
to you in that context.
... but doing something
with undefined behavior, and expecting a specific behavior,
seems "wrong" to me.

I would basically agree with that statement - with limitations. In the
context of the C standard, "undefined behavior" means only that the
standard doesn't define the behavior; it does not prohibit other
documents from defining it, such as the compiler's documentation, and
there's nothing wrong with relying upon that's compiler's documentation
for code that's intended to be used only with that compiler.

However, the wrongness described by that statement doesn't seem
applicable to the S/360 emulator. In the context of that statement,
"expecting" is something that a developer does, not something that the
emulator does.

It would indeed be wrong for the developer of code that's intended to be
portable, to have any expectations about how a 32-bit C shift of a
32-bit integer is implemented; but that's precisely because there's no
wrong way for an implementation to implement it.
 
T

Tim Rentsch

Keith Thompson said:
Not quite. N1570 6.5.7p3 (emphasis added):

The integer promotions are performed on each of the operands. The
type of the result is that of the promoted left operand. If the
value of the right operand is negative or is greater than *or
equal to* the width of the promoted left operand, the behavior
is undefined.

To be fair, he was drawing his conclusions based (partly) on my
earlier statements, and those statements were wrong. It's true
that the conclusion he reached isn't exactly right, but neither
is my earlier statement and that inaccuracy should also be
pointed out if this one is.
 
G

guinness.tony

The integer promotions are performed on each of the operands. The
type of the result is that of the promoted left operand. If the
value of the right operand is negative or is greater than *or
equal to* the width of the promoted left operand, the behavior
is undefined.

I was amazed at this wording and had to double-check it for myself.
It says that the VALUE of the right operand is compared with the WIDTH
of the (promoted) left operand. Surely this is wrong?
 
E

Eric Sosman

I was amazed at this wording and had to double-check it for myself.
It says that the VALUE of the right operand is compared with the WIDTH
of the (promoted) left operand. Surely this is wrong?

What do you think is wrong about it?

The value of the right operand is the shift distance:
`x >> 1' right-shifts by one bit, `y << 3' left-shifts by 3.
The left operand holds the bit pattern prior to shifting, and
its width is the number of bits (zero or one) that it holds.
The paragraph says (1) you can't shift by a negative distance,
and (2) the shift distance must be strictly less than the
number of bits in the pattern.
 
J

James Kuyper

I was amazed at this wording and had to double-check it for myself.
It says that the VALUE of the right operand is compared with the WIDTH
of the (promoted) left operand. Surely this is wrong?

The value of the right operand is the number of bits to be shifted. The
width of the left operand is the count of the number of bits that are
available to be shifted. What strikes you as odd about comparing those
two numbers?
 
G

guinness.tony

I was amazed at this wording and had to double-check it for myself.

It says that the VALUE of the right operand is compared with the WIDTH

of the (promoted) left operand. Surely this is wrong?

D'Oh! Please ignore my ramblings, above. I dozily thought the
discussion was on symmetric binary operators. I shall read more
context next time!
 
D

David Thompson

(snip on shift operations equal to or longer than the operand
being shifted, then I wrote) <snip>
I presume somewhere in the early days of computers, some did
shift for the specified amount. For S/360, the shift amount
is the low 6 bits of the sum of two 32 bit registers and
a 12 bit unsigned constant. If you didn't limit it, user
programs could go off on an endless (or greater than MTBF,
whichever comes first) loop.
Shift instructions are RS not RX; the second operand is the sum of
u12bit constant and one 32bit GPR unless it is (specified as) R0.
As noted, the 8086 and 8088 allow up to 255. You can count the
processor cycles used. Many others take the low five bits for 32 bit
shifts. (I believe including all later x86 processors.)
My recollection is that once gates in LSI become numerous enough (with
usable yield) to make barrel shifters cheap, pretty much everyone
switched to them, and they naturally truncate the shift (or rotate)
count to the data path width.
 
Ö

Öö Tiib

Be careful with terminology. Yes, 0xff and 0xffff have integer
type -- not just by default, but always. int, unsigned int,
unsigned long, unsigned long long, short, signed char, and _Bool,
among others, are all integer types.

Aren't the full integer type names like "signed long long int"
(notice "int"!)?
 
G

glen herrmannsfeldt

(snip)
Shift instructions are RS not RX; the second operand is the sum of
u12bit constant and one 32bit GPR unless it is (specified as) R0.

I never thought about needing two registers, but yes they are RS.
Four bits don't do anything. Interestingly, the new z/Architecture
instructions for 64 bit registers (in RSY format) also use a 6 bit
shift value. There are no double 64 bit register shift instructions.
My recollection is that once gates in LSI become numerous enough (with
usable yield) to make barrel shifters cheap, pretty much everyone
switched to them, and they naturally truncate the shift (or rotate)
count to the data path width.

Well, it isn't so hard to put in the extra logic to zero (or 1) the
register for larger shift values, but it does seem to be rare.
But for non-LSI processors, it might be a microcode loop.

-- glen
 
J

James Kuyper

Aren't the full integer type names like "signed long long int"
(notice "int"!)?

Well, yes, but the standard allows shorter forms, and many people,
myself included, routinely use the shortest form for each type. It's not
explicitly stated anywhere in the standard, but a careful examination of
6.7.2p2 reveals two key patterns:

The keyword "signed" is needed only with char. For short, int, long, and
long long, signed is allowed, but is unnecessary because it's the
default. Exception: "for bit-fields, it is implementation-defined
whether the specifier int designates the same type as signed int or the
same type as unsigned int" (6.7.2p5). It's almost never a good idea rely
on that, so you should explicitly say "signed int" if that's what you want.

The keyword "int" can be dropped if you use any of the other
type-specifier keywords.
 
G

glen herrmannsfeldt

Robert Wessel said:
OTOH, fixing a barrel shifter to produce "zero" when the shift count
equals or exceeds width of the item being shifted is not hard, and
would result in an arguably more useful behavior.

I have in the past suspected that some hardware features were
selected based on the requirements of Fortran. Once hardware starts
being made a certain way, languages will try to accomdate that.

However, the shift operations came late to Fortran, so that seems
not true in that case. The Fortran ISHFT function not only doesn't
have a requirement on the maximum shift value, but it uses the
sign of the value to select the shift direction. As hardware using
the sign of the shift value is relatively rare (I believe the
PDP-10 does it), that requires a conditional test on a variable
shift operation, and likely another one to allow for large shift
values.

C accomodates what the hardware sometimes (often) provides.
You can add the tests if you need them, leave them out if you don't.

-- glen
 
K

Keith Thompson

Öö Tiib said:
Aren't the full integer type names like "signed long long int"
(notice "int"!)?

Yes, most but not all integer types have names that include the keyword
"int".

In general, a predefined type name is a sequence of keywords (in
arbitrary order), and there are rules about which ones you can omit;
you'll find a complete list in section 6.7.2 of the C standard, "Type
specifiers".

The keyword "int" by itself is the name of one particular type; it can
also be referred to as "signed int", "signed", or "int signed". "int"
is generally considered its primary name, but the standard doesn't say
so. (In fact, all types have names that do not include the "int"
keyword, but that's not a particularly useful fact.)
 
K

Keith Thompson

glen herrmannsfeldt said:
However, the shift operations came late to Fortran, so that seems
not true in that case. The Fortran ISHFT function not only doesn't
have a requirement on the maximum shift value, but it uses the
sign of the value to select the shift direction. As hardware using
the sign of the shift value is relatively rare (I believe the
PDP-10 does it), that requires a conditional test on a variable
shift operation, and likely another one to allow for large shift
values.

I suspect most shifts use a constant shift amount. Fortran compilers
can probably take advantage of that to avoid the conditional test
in most cases.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top