#! /bin/sh -e # All lines beginning with `# DP:' are a description of the patch. # DP: Fix for complex math on alpha if [ $# -eq 3 -a "$2" = '-d' ]; then pdir="-d $3" elif [ $# -ne 1 ]; then echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 fi case "$1" in -patch) patch $pdir -f --no-backup-if-mismatch -p1 < $0;; -unpatch) patch $pdir -f --no-backup-if-mismatch -R -p1 < $0;; *) echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 esac exit 0 (from Joel Klecker's original message): I've tested this patch with building glibc and it enables it to compile, I haven't been able to test the resulting binaries yet, however. I assume this will fix the g77 problems too. * flow.c (insn_dead_p): Don't kill part of a complex number. * emit-rtl.c (gen_lowpart_common): Handle narrow complex reg values. (gen_highpart): Likewise. * calls.c (expand_call): Narrow complex variable uses two regs. * alpha/alpha.h (ALPHA_ARG_SIZE): Likewise. (HARD_REGNO_NREGS): Likewise. diff -ur gcc-2.95.2/gcc/calls.c gcc-2.95.2.patched/gcc/calls.c --- gcc-2.95.2/gcc/calls.c Fri May 7 21:58:39 1999 +++ gcc-2.95.2.patched/gcc/calls.c Sat Feb 19 14:26:21 2000 @@ -1499,6 +1499,11 @@ validize_mem (args[i].value), nregs, args[i].mode); + /* Indicate two regs used to hold a short complex arg. */ + if (GET_MODE_CLASS (args[i].mode) == MODE_COMPLEX_FLOAT + && GET_MODE_SIZE (args[i].mode) <= UNITS_PER_WORD) + nregs = 2; + /* Handle calls that pass values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ if (GET_CODE (reg) == PARALLEL) diff -ur gcc-2.95.2/gcc/config/alpha/alpha.h gcc-2.95.2.patched/gcc/config/alpha/alpha.h --- gcc-2.95.2/gcc/config/alpha/alpha.h Fri Jun 25 01:09:12 1999 +++ gcc-2.95.2.patched/gcc/config/alpha/alpha.h Sat Feb 19 14:28:45 2000 @@ -622,7 +622,10 @@ 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) + ((GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ + && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \ + ? 2 \ + : ((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 @@ -1070,12 +1073,16 @@ #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) (CUM) = 0 /* Define intermediate macro to compute the size (in registers) of an argument - for the Alpha. */ + for the Alpha. + A short complex arg takes two registers. */ #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) + ((GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ + && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \ + ? 2 \ + : ((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 of mode MODE and data type TYPE. diff -ur gcc-2.95.2/gcc/emit-rtl.c gcc-2.95.2.patched/gcc/emit-rtl.c --- gcc-2.95.2/gcc/emit-rtl.c Wed Aug 11 03:28:52 1999 +++ gcc-2.95.2.patched/gcc/emit-rtl.c Sat Feb 19 14:31:19 2000 @@ -749,6 +749,15 @@ && ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode) && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x))) return 0; + else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_COMPLEX_FLOAT + && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD + && REGNO (x) < FIRST_PSEUDO_REGISTER) + { + if (REG_FUNCTION_VALUE_P (x)) + return gen_rtx (SUBREG, mode, x, 0); + else + return gen_rtx (REG, mode, REGNO (x)); + } else if (REGNO (x) < FIRST_PSEUDO_REGISTER /* integrate.c can't handle parts of a return value register. */ && (! REG_FUNCTION_VALUE_P (x) @@ -972,11 +981,6 @@ { if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode) return XEXP (x, 0); - else if (WORDS_BIG_ENDIAN - && GET_MODE_BITSIZE (mode) < BITS_PER_WORD - && REG_P (x) - && REGNO (x) < FIRST_PSEUDO_REGISTER) - fatal ("Unable to access real part of complex value in a hard register on this target"); else if (WORDS_BIG_ENDIAN) return gen_highpart (mode, x); else @@ -995,11 +999,6 @@ return XEXP (x, 1); else if (WORDS_BIG_ENDIAN) return gen_lowpart (mode, x); - else if (!WORDS_BIG_ENDIAN - && GET_MODE_BITSIZE (mode) < BITS_PER_WORD - && REG_P (x) - && REGNO (x) < FIRST_PSEUDO_REGISTER) - fatal ("Unable to access imaginary part of complex value in a hard register on this target"); else return gen_highpart (mode, x); } @@ -1134,6 +1133,16 @@ word = ((GET_MODE_SIZE (GET_MODE (x)) - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)) / UNITS_PER_WORD); + + if (GET_MODE_CLASS (GET_MODE (x)) == MODE_COMPLEX_FLOAT + && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD + && REGNO (x) < FIRST_PSEUDO_REGISTER) + { + if (REG_FUNCTION_VALUE_P (x)) + return gen_rtx (SUBREG, mode, x, 1); + else + return gen_rtx (REG, mode, REGNO (x) + 1); + } if (REGNO (x) < FIRST_PSEUDO_REGISTER /* integrate.c can't handle parts of a return value register. */ diff -ur gcc-2.95.2/gcc/flow.c gcc-2.95.2.patched/gcc/flow.c --- gcc-2.95.2/gcc/flow.c Wed Aug 4 03:09:48 1999 +++ gcc-2.95.2.patched/gcc/flow.c Sat Feb 19 14:34:02 2000 @@ -2995,6 +2995,10 @@ while (--n > 0) if (REGNO_REG_SET_P (needed, regno+n)) return 0; + + /* Don't allow part of a complex number to be deleted. */ + if (GET_MODE_CLASS (GET_MODE (r)) == MODE_COMPLEX_FLOAT) + return 0; } return 1;