[INTEL NAVIGATION HEADER]

Unexpected Float to Double Promotion in iC960 R3.0 and R3.5

(#3131) Unexpected Float to Double Promotion in iC960 R3.0 and R3.5

Unexpected Float to Double Promotion in iC960 R3.0 and R3.5

Unexpected FLOAT to DOUBLE promotions can occur when using traditional (non-ANSI) syntax for formal parameter (argument) declaration in a function definition in iC960 R3.0 and R3.5. This article provides an explanation for the code emitted by the compilers.

The behavior of the iC960 R3.0 and R3.5 compilers conforms to the "ANSI C" standard. Following is an excerpt from section 3.3.2.2 of the "ANSI C" standard, American National Standard X3.159-1989, under the heading `Semantics':

" If the expression that denotes the called function has a type that does not include a prototype, the integral promotions are performed on each argument and arguments that have type FLOAT are promoted to DOUBLE. These are called the `default argument promotions'. ... "

This specification is also documented in section 6.3.5 of C: A Reference Manual, (Third Edition) by Harbison and Steele, which is made available as part of the iC960 R3.x product.

The difference between an ANSI prototyped formal parameter and a traditional (non-prototyped) formal parameter can be shown for "a" as:

ANSI prototyped Traditional
void foo (float a) void foo (a)
float a;

As per the ANSI standard, in the absence of a prototype for a function definition, the iC960 R3.0 and R3.5 compilers will promote and demote formal parameters from FLOAT to DOUBLE and back to FLOAT again across a call. For example, given the code fragment:

void foo (a)
float a;
{
       printf("%f\n",a);
}

the compilers assume that upon entry to the function "foo" the formal parameter "a" has been promoted and passed as a DOUBLE by the calling function. Consequently, code emitted by the compilers when compiling the "foo" function will contain appropriate instructions to demote the parameter back to a FLOAT. Additional code emitted by the compilers will promote the parameter to a DOUBLE again prior to the call to printf().

iC960 R3.0 emits a different instruction sequence than the R3.5 compiler, but the behavior remains the same. ic960 R3.5 is used in the discussion which follows. When iC960 R3.5 is invoked and the specified 80960 microprocessor architecture is either "SB" or "KB" or "MC", the following instructions are emitted (floating point, local and global register assignments may vary, except for g0 and g2):

The compiler utilizes the on-chip floating point capabilities of these architectures. However, when iC960 R3.5 is invoked and the specified 80960 microprocessor architecture is either "SA" or "KA" or "CA", the following instructions are emitted (local and global register assignments may vary, except for g0 and g2):

The compiler uses calls to library functions in these architectures, hence the call to ___truncdfsf2 to demote the formal parameter from DOUBLE to FLOAT upon entry to "foo" and the call to ___extendsfdf2 to promote the formal parameter to DOUBLE prior to the branch to _printf.

The overhead associated with this promotion and demotion can be avoided between calls among user-defined functions by prototyping the formal parameters or by simply declaring them as DOUBLE in both the calling and called functions. Standard C Library functions declare all formal floating point parameters as type DOUBLE, as per the ANSI C standard, so the promotion overhead can only be avoided when calling these functions by declaring the parameters as type DOUBLE in the calling function.

For example, when the code fragment:

is compiled with a "CA" architecture at optimization level 2 (-O2), the iC960 R3.5 compiler emits the following instructions:

The use of ANSI prototyping in the formal parameter declaration inhibits the demotion code that was seen previously, however the promotion code to comply with the ANSI-defined requirement of the Standard C Library is still present.

Elimination of the promotion code is only possible by declaring the formal parameter "a" as type DOUBLE instead of type FLOAT. If the programmer were to improperly prototype these Standard C Library functions in a user-defined calling function, the types of the arguments when they are passed would differ from their expected type upon receipt by the function, resulting in a runtime error. This same type of problem can also occur when a user-defined function calls another user-defined function and one of the functions has ANSI prototyping and the other function contains traditional declarations.

In the case where the specified 80960 architecture is either "SA" or "KA" or "CA", there are many numeric library functions which are called when floating point expressions appear in the source code. These numeric library functions also declare floating point formal parameters as type DOUBLE, per the ANSI C standard, so expressions can cause unexpected promotions of actual parameters of type FLOAT. Similar to the Standard C Library, the only way to avoid the promotion overhead is to declare the expression parameters as type DOUBLE in the function.

Finally, please note that the ___truncdfsf2 function in the Intel- supplied R3.0 and R3.5 libhka.a and libhca.a libraries contains a bug whereby register G2 is not preserved. If you are working on a 80960 "KA", "SA" or "CA" microprocessor design and have need for a corrected version of this function, please request it from DTO Customer Support at 1-800-843-4481. If you are located outside of the continental United States please contact your local sales representative.

Free Web Hosting



Legal Stuff © 1997 Intel Corporation