This reflects an x86-64 ABI change (or clarification) that now requires XCmode return values to be passed through st0 and st1 rather than memory. Having looked at all this again I would question one currently (and previously) existing construct, though (but I don't immediately know how to address this): x86_libcall_value says DCmode gets returned in FIRST_SSE_REG, but since DCmode entirely fits into one xmm register this does not seem to imply use of xmm0 and xmm1 for each of the halves. Bootstrapped and tested on x86_64-unknown-linux-gnu. 2004-12-16 Jan Beulich PR/17603 * config/i386/i386.c (enum x86_64_reg_class): Define X86_64_COMPLEX_X87_CLASS. (x86_64_reg_class_names): Add name for X86_64_COMPLEX_X87_CLASS. (merge_classes): Handle X86_64_COMPLEX_X87_CLASS. (classify_argument): XCmode is X86_64_COMPLEX_X87_CLASS. (examine_argument): X86_64_COMPLEX_X87_CLASS requires two registers when dealing with a return value. (construct_container): Handle X86_64_COMPLEX_X87_CLASS. Eliminate impossible case of two X87/X87UP pairs (this now is being expressed by a single COMPLEX_X87). (x86_libcall_value): XCmode gets returned in st0/st1. --- /home/jbeulich/src/gcc/mainline/2004-12-13.08.53/gcc/config/i386/i386.c 2004-12-13 08:30:01.000000000 +0100 +++ 2004-12-13.08.53/gcc/config/i386/i386.c 2004-12-16 13:38:29.751511752 +0100 @@ -947,10 +947,11 @@ enum x86_64_reg_class X86_64_SSEUP_CLASS, X86_64_X87_CLASS, X86_64_X87UP_CLASS, + X86_64_COMPLEX_X87_CLASS, X86_64_MEMORY_CLASS }; static const char * const x86_64_reg_class_name[] = - {"no", "integer", "integerSI", "sse", "sseSF", "sseDF", "sseup", "x87", "x87up", "no"}; + {"no", "integer", "integerSI", "sse", "sseSF", "sseDF", "sseup", "x87", "x87up", "cplx87", "no"}; #define MAX_CLASSES 4 static int classify_argument (enum machine_mode, tree, @@ -2066,9 +2067,14 @@ merge_classes (enum x86_64_reg_class cla || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) return X86_64_INTEGER_CLASS; - /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used. */ - if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS - || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS) + /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, + MEMORY is used. */ + if (class1 == X86_64_X87_CLASS + || class1 == X86_64_X87UP_CLASS + || class1 == X86_64_COMPLEX_X87_CLASS + || class2 == X86_64_X87_CLASS + || class2 == X86_64_X87UP_CLASS + || class2 == X86_64_COMPLEX_X87_CLASS) return X86_64_MEMORY_CLASS; /* Rule #6: Otherwise class SSE is used. */ @@ -2348,8 +2354,10 @@ classify_argument (enum machine_mode mod classes[1] = X86_64_SSEDF_CLASS; return 2; case XCmode: + classes[0] = X86_64_COMPLEX_X87_CLASS; + return 1; case TCmode: - /* These modes are larger than 16 bytes. */ + /* This modes is larger than 16 bytes. */ return 0; case V4SFmode: case V4SImode: @@ -2421,6 +2429,8 @@ examine_argument (enum machine_mode mode if (!in_return) return 0; break; + case X86_64_COMPLEX_X87_CLASS: + return in_return ? 2 : 0; case X86_64_MEMORY_CLASS: abort (); } @@ -2479,6 +2489,7 @@ construct_container (enum machine_mode m case X86_64_SSEDF_CLASS: return gen_rtx_REG (mode, SSE_REGNO (sse_regno)); case X86_64_X87_CLASS: + case X86_64_COMPLEX_X87_CLASS: return gen_rtx_REG (mode, FIRST_STACK_REG); case X86_64_NO_CLASS: /* Zero sized array, struct or class. */ @@ -2497,11 +2508,6 @@ construct_container (enum machine_mode m && (mode == CDImode || mode == TImode || mode == TFmode) && intreg[0] + 1 == intreg[1]) return gen_rtx_REG (mode, intreg[0]); - if (n == 4 - && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS - && class[2] == X86_64_X87_CLASS && class[3] == X86_64_X87UP_CLASS - && mode != BLKmode) - return gen_rtx_REG (XCmode, FIRST_STACK_REG); /* Otherwise figure out the entries of the PARALLEL. */ for (i = 0; i < n; i++) @@ -3035,8 +3041,8 @@ ix86_libcall_value (enum machine_mode mo case TFmode: return gen_rtx_REG (mode, FIRST_SSE_REG); case XFmode: - return gen_rtx_REG (mode, FIRST_FLOAT_REG); case XCmode: + return gen_rtx_REG (mode, FIRST_FLOAT_REG); case TCmode: return NULL; default: