This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
complex support on alpha
- To: egcs at cygnus dot com
- Subject: complex support on alpha
- From: Weiwen Liu <liu at hepvms dot physics dot yale dot edu>
- Date: Thu, 02 Oct 1997 00:02:42 -0400 (EDT)
Hi,
egcs on alpha-dec-osf4.0 fails to generate correct code for
gcc.c-torture/execute/complex-5.c
in the testsuite, because gcc does not calculate correctly the number of
registers needed for 'float __complex__'. Instead of 2 registers, gcc
says only one register is needed.
egcs generates rtl's for complex-5.c:
(insn 4 2 6 (set (mem:SF (reg:DI 65))
(reg:SF 48 $f16)) -1 (nil)
(nil))
(insn 6 4 8 (set (mem:SF (plus:DI (reg:DI 65)
(const_int 4)))
(reg:SF 48 $f16)) -1 (nil)
(nil))
===> register $f16 is used to pass both real and imagine part, and the
===> real part is lost in function f in complex-5.c
(insn 8 6 10 (set (mem:SF (plus:DI (reg:DI 65)
(const_int 8)))
(reg:SF 49 $f17)) -1 (nil)
(nil))
(insn 10 8 11 (set (mem:SF (plus:DI (reg:DI 65)
(const_int 12)))
(reg:SF 49 $f17)) -1 (nil)
(nil))
The following patch will calculate number of registers for
complex arguments correctly and compile complex-5.c correctly.
With this patch, egcs generates correct code for the following
program:
/*
long int __complex__ t5 (long int __complex__ a, long int __complex__ b)
{
return a + b;
}
*/
float __complex__ t1 (float __complex__ a, float __complex__ b)
{
return a + b;
}
double __complex__ t2 (double __complex__ a, double __complex__ b)
{
return a + b;
}
short __complex__ t3 (short __complex__ a, short __complex__ b)
{
return a + b;
}
int __complex__ t4 (int __complex__ a, int __complex__ b)
{
return a + b;
}
float __complex__ a1 = 1. + 2.i;
float __complex__ b1 = 3. + 4.i;
float __complex__ c1 = 4. + 6.i;
double __complex__ a2 = 1.L + 2.Li;
double __complex__ b2 = 3.L + 4.Li;
double __complex__ c2 = 4.L + 6.Li;
short __complex__ a3 = 1 + 2i;
short __complex__ b3 = 3 + 4i;
short __complex__ c3 = 4 + 6i;
int __complex__ a4 = 1 + 2i;
int __complex__ b4 = 3 + 4i;
int __complex__ c4 = 4 + 6i;
/*
long int __complex__ a5 = 1L + 2Li;
long int __complex__ b5 = 3L + 4Li;
long int __complex__ c5 = 4L + 6Li;
*/
int main()
{
if (t1(a1, b1) != c1)
abort ();
if (t2(a2, b2) != c2)
abort ();
if (t3(a3, b3) != c3)
abort ();
if (t4(a4, b4) != c4)
abort ();
/*
if (t5(a5, b5) != c5)
abort ();
*/
return 0;
}
Note that "long int __complex__" parts are commented out because gcc
does not accept it even though gcc.info says it supports. I have a
patch to enable "long int __complex__" support. If you need this
patch, let me know.
Weiwen
Wed Oct 2 23:30:00 Weiwen Liu <liu@hepunix.physics.yale.edu>
* regs.h: Correctly calculates number of registers needed.
* emit-rtl.c (gen_lowpart_common, gen_highpart): Ditto.
* config/alpha/alpha.h: Ditto.
* config/alpha/alpha.h: Use $f0 and $f1 for complex float.
*** gcc/regs.h.orig Tue Sep 30 01:07:59 1997
--- gcc/regs.h Wed Oct 1 00:20:26 1997
*************** Boston, MA 02111-1307, USA. */
*** 27,33 ****
valid way to get this value. You cannot get it from the regno. */
#define REG_SIZE(R) \
! ((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* Maximum register number used in this function, plus one. */
--- 27,36 ----
valid way to get this value. You cannot get it from the regno. */
#define REG_SIZE(R) \
! (GET_MODE_SIZE (GET_MODE (R)) == 0? \
! 0:(((GET_MODE_UNIT_SIZE (GET_MODE (R)) + (UNITS_PER_WORD - 1)) \
! / UNITS_PER_WORD) * (GET_MODE_SIZE (GET_MODE (R)) \
! / GET_MODE_UNIT_SIZE (GET_MODE (R)))))
/* Maximum register number used in this function, plus one. */
*** gcc/emit-rtl.c.orig Mon Sep 22 13:41:24 1997
--- gcc/emit-rtl.c Tue Sep 30 23:09:20 1997
*************** gen_lowpart_common (mode, x)
*** 635,644 ****
/ UNITS_PER_WORD)))
return 0;
! if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
! word = ((GET_MODE_SIZE (GET_MODE (x))
! - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
! / UNITS_PER_WORD);
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
&& (GET_MODE_CLASS (mode) == MODE_INT
--- 635,647 ----
/ UNITS_PER_WORD)))
return 0;
! if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) >0)
! word = ((GET_MODE_UNIT_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
! / UNITS_PER_WORD)
! * (GET_MODE_SIZE (GET_MODE (x))
! / GET_MODE_UNIT_SIZE (GET_MODE (x)))
! - ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1))
! / UNITS_PER_WORD);
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
&& (GET_MODE_CLASS (mode) == MODE_INT
*************** gen_highpart (mode, x)
*** 1013,1022 ****
int word = 0;
if (! WORDS_BIG_ENDIAN
! && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
! word = ((GET_MODE_SIZE (GET_MODE (x))
! - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
! / UNITS_PER_WORD);
/*
* ??? This fails miserably for complex values being passed in registers
--- 1016,1028 ----
int word = 0;
if (! WORDS_BIG_ENDIAN
! && GET_MODE_SIZE (GET_MODE (x)) > 0)
! word = ((GET_MODE_UNIT_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
! / UNITS_PER_WORD)
! * (GET_MODE_SIZE (GET_MODE (x))
! / GET_MODE_UNIT_SIZE (GET_MODE (x)))
! - ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1))
! / UNITS_PER_WORD);
/*
* ??? This fails miserably for complex values being passed in registers
*** gcc/config/alpha/alpha.h.orig Thu Sep 25 10:21:11 1997
--- gcc/config/alpha/alpha.h Wed Oct 1 12:33:43 1997
*************** extern void override_options ();
*** 515,521 ****
but can be less for certain modes in special long registers. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
! ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
On Alpha, the integer registers can hold any mode. The floating-point
--- 515,525 ----
but can be less for certain modes in special long registers. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
! (GET_MODE_SIZE (MODE) == 0? \
! 0:(((GET_MODE_UNIT_SIZE (MODE) + (UNITS_PER_WORD - 1)) \
! / UNITS_PER_WORD) * (GET_MODE_SIZE (MODE) \
! / GET_MODE_UNIT_SIZE (MODE))))
! /* ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)*/
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
On Alpha, the integer registers can hold any mode. The floating-point
*************** enum reg_class { NO_REGS, GENERAL_REGS,
*** 891,901 ****
#define FUNCTION_VALUE(VALTYPE, FUNC) \
gen_rtx (REG, \
(INTEGRAL_MODE_P (TYPE_MODE (VALTYPE)) \
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
? word_mode : TYPE_MODE (VALTYPE), \
((TARGET_FPREGS \
&& (TREE_CODE (VALTYPE) == REAL_TYPE \
! || TREE_CODE (VALTYPE) == COMPLEX_TYPE)) \
? 32 : 0))
/* Define how to find the value returned by a library function
--- 895,909 ----
#define FUNCTION_VALUE(VALTYPE, FUNC) \
gen_rtx (REG, \
(INTEGRAL_MODE_P (TYPE_MODE (VALTYPE)) \
+ && (GET_MODE_CLASS(TYPE_MODE (VALTYPE)) \
+ != MODE_COMPLEX_INT) \
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
? word_mode : TYPE_MODE (VALTYPE), \
((TARGET_FPREGS \
&& (TREE_CODE (VALTYPE) == REAL_TYPE \
! || TREE_CODE (VALTYPE) == COMPLEX_TYPE) \
! && (GET_MODE_CLASS(TYPE_MODE (VALTYPE)) \
! != MODE_COMPLEX_INT)) \
? 32 : 0))
/* Define how to find the value returned by a library function
*************** enum reg_class { NO_REGS, GENERAL_REGS,
*** 953,959 ****
#define ALPHA_ARG_SIZE(MODE, TYPE, NAMED) \
((MODE) != BLKmode \
! ? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD \
: (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
/* Update the data in CUM to advance over an argument
--- 961,970 ----
#define ALPHA_ARG_SIZE(MODE, TYPE, NAMED) \
((MODE) != BLKmode \
! ? (GET_MODE_SIZE (MODE) > 0? \
! (GET_MODE_UNIT_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD \
! * GET_MODE_SIZE (MODE) / GET_MODE_UNIT_SIZE (MODE) \
! : 0) \
: (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
/* Update the data in CUM to advance over an argument
The result from "make check-gcc" with this patch is
=== gcc Summary ===
# of expected passes 4879
# of unexpected failures 8
# of expected failures 4
# of unsupported tests 7
FAIL: gcc.c-torture/compile/961203-1.c, -O0
FAIL: gcc.c-torture/compile/961203-1.c, -O1
FAIL: gcc.c-torture/compile/961203-1.c, -O2
FAIL: gcc.c-torture/compile/961203-1.c, -O2 -fomit-frame-pointer -finline-functions
FAIL: gcc.c-torture/execute/ieee/fp-cmp-1.c execution, -O0
FAIL: gcc.c-torture/execute/ieee/fp-cmp-1.c execution, -O1
FAIL: gcc.c-torture/execute/ieee/fp-cmp-1.c execution, -O2
FAIL: gcc.c-torture/execute/ieee/fp-cmp-1.c execution, -O2 -fomit-frame-pointer -finline-functions