From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1270 invoked by alias); 6 Nov 2007 03:12:40 -0000 Received: (qmail 1253 invoked by uid 22791); 6 Nov 2007 03:12:38 -0000 X-Spam-Check-By: sourceware.org Received: from e36.co.us.ibm.com (HELO e36.co.us.ibm.com) (32.97.110.154) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 06 Nov 2007 03:12:34 +0000 Received: from d03relay04.boulder.ibm.com (d03relay04.boulder.ibm.com [9.17.195.106]) by e36.co.us.ibm.com (8.13.8/8.13.8) with ESMTP id lA63CSgu006027 for ; Mon, 5 Nov 2007 22:12:28 -0500 Received: from d03av04.boulder.ibm.com (d03av04.boulder.ibm.com [9.17.195.170]) by d03relay04.boulder.ibm.com (8.13.8/8.13.8/NCO v8.5) with ESMTP id lA63CSuE125176 for ; Mon, 5 Nov 2007 20:12:28 -0700 Received: from d03av04.boulder.ibm.com (loopback [127.0.0.1]) by d03av04.boulder.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id lA63CSgt018871 for ; Mon, 5 Nov 2007 20:12:28 -0700 Received: from localhost (vervain.rchland.ibm.com [9.5.250.62]) by d03av04.boulder.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id lA63CRgb018849; Mon, 5 Nov 2007 20:12:28 -0700 Date: Tue, 06 Nov 2007 03:12:00 -0000 From: Peter Bergner To: David Edelsohn Cc: "gcc-patches@gcc.gnu.org" Subject: Re: [PING][PATCH][libobjc,rs6000] Fix DDmode ICE on testcase. Message-ID: <20071106031227.GA20656@vervain.rchland.ibm.com> References: <1191607765.7169.32.camel@otta> <200710251353.l9PDrcEl031634@makai.watson.ibm.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200710251353.l9PDrcEl031634@makai.watson.ibm.com> User-Agent: Mutt/1.5.6i X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-11/txt/msg00243.txt.bz2 On Thu, Oct 25, 2007 at 09:53:38AM -0400, David Edelsohn wrote: > AIX uses natural alignment for the new decimal float types, so > please remove those ABI changes from the patch. In other words, > ADJUST_FIELD_ALIGN and ROUND_TYPE_ALIGN where the alignment depends upon > TARGET_ALIGN_NATURAL. ALIGN_POWER does not change the alignment of > decimal float. Ok, I removed the ADJUST_FIELD_ALIGN changes in aix.h, linux64.h, as well as the rs6000_special_round_type_align(), and libobjc/encoding.c changes. This updated patch has passed bootstrap and regtesting on powerpc64-linux running the testsuite in both 32-bit and 64-bit modes. Is this ok for mainline now? Peter gcc/ * config/rs6000/rs6000.c (invalid_e500_subreg, rs6000_legitimate_offset_address_p, legitimate_lo_sum_address_p, rs6000_legitimize_address, rs6000_legitimize_reload_address, rs6000_legitimate_address, function_arg_advance, spe_build_register_parallel, rs6000_spe_function_arg, rs6000_split_multireg_move, spe_func_has_64bit_regs_p, emit_frame_save, gen_frame_mem_offset, rs6000_function_value, rs6000_libcall_value, rs6000_dwarf_register_span): Handle DDmode and TDmode similarly to DFmode and TFmode. * config/rs6000/rs6000.h (LOCAL_ALIGNMENT, MEMBER_TYPE_FORCES_BLK, DATA_ALIGNMENT, CLASS_MAX_NREGS, CANNOT_CHANGE_MODE_CLASS): Likewise. gcc/testsuite/ * gcc.dg/dfp/ddmode-ice.c: New test. Index: config/rs6000/rs6000.c =================================================================== --- config/rs6000/rs6000.c (revision 129901) +++ config/rs6000/rs6000.c (working copy) @@ -3115,13 +3115,16 @@ invalid_e500_subreg (rtx op, enum machin && (mode == SImode || mode == DImode || mode == TImode) && REG_P (SUBREG_REG (op)) && (GET_MODE (SUBREG_REG (op)) == DFmode - || GET_MODE (SUBREG_REG (op)) == TFmode)) + || GET_MODE (SUBREG_REG (op)) == TFmode + || GET_MODE (SUBREG_REG (op)) == DDmode + || GET_MODE (SUBREG_REG (op)) == TDmode)) return true; /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and reg:TI. */ if (GET_CODE (op) == SUBREG - && (mode == DFmode || mode == TFmode) + && (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode) && REG_P (SUBREG_REG (op)) && (GET_MODE (SUBREG_REG (op)) == DImode || GET_MODE (SUBREG_REG (op)) == TImode)) @@ -3390,12 +3393,12 @@ rs6000_legitimate_offset_address_p (enum break; case TFmode: + case TDmode: if (TARGET_E500_DOUBLE) return (SPE_CONST_OFFSET_OK (offset) && SPE_CONST_OFFSET_OK (offset + 8)); case TImode: - case TDmode: if (mode == TFmode || mode == TDmode || !TARGET_POWERPC64) extra = 12; else if (offset & 3) @@ -3474,6 +3477,7 @@ legitimate_lo_sum_address_p (enum machin return false; /* Restrict addressing for DI because of our SUBREG hackery. */ if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode || mode == DImode)) return false; x = XEXP (x, 1); @@ -3488,7 +3492,8 @@ legitimate_lo_sum_address_p (enum machin return false; if (GET_MODE_BITSIZE (mode) > 64 || (GET_MODE_BITSIZE (mode) > 32 && !TARGET_POWERPC64 - && !(TARGET_HARD_FLOAT && TARGET_FPRS && mode == DFmode))) + && !(TARGET_HARD_FLOAT && TARGET_FPRS + && (mode == DFmode || mode == DDmode)))) return false; return CONSTANT_P (x); @@ -3610,7 +3615,8 @@ rs6000_legitimize_address (rtx x, rtx ol && CONSTANT_P (x) && GET_MODE_NUNITS (mode) == 1 && (GET_MODE_BITSIZE (mode) <= 32 - || ((TARGET_HARD_FLOAT && TARGET_FPRS) && mode == DFmode))) + || ((TARGET_HARD_FLOAT && TARGET_FPRS) + && (mode == DFmode || mode == DDmode)))) { rtx reg = gen_reg_rtx (Pmode); emit_insn (gen_elf_high (reg, x)); @@ -3624,7 +3630,8 @@ rs6000_legitimize_address (rtx x, rtx ol && GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE && CONSTANT_P (x) - && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode) + && ((TARGET_HARD_FLOAT && TARGET_FPRS) + || (mode != DFmode && mode != DDmode)) && mode != DImode && mode != TImode) { @@ -3980,6 +3987,7 @@ rs6000_legitimize_reload_address (rtx x, && GET_CODE (XEXP (x, 1)) == CONST_INT && !SPE_VECTOR_MODE (mode) && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode || mode == DImode)) && !ALTIVEC_VECTOR_MODE (mode)) { @@ -4021,12 +4029,12 @@ rs6000_legitimize_reload_address (rtx x, && !flag_pic #endif /* Don't do this for TFmode or TDmode, since the result isn't offsettable. - The same goes for DImode without 64-bit gprs and DFmode + The same goes for DImode without 64-bit gprs and DFmode and DDmode without fprs. */ && mode != TFmode && mode != TDmode && (mode != DImode || TARGET_POWERPC64) - && (mode != DFmode || TARGET_POWERPC64 + && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64 || (TARGET_FPRS && TARGET_HARD_FLOAT))) { #if TARGET_MACHO @@ -4089,11 +4097,11 @@ rs6000_legitimize_reload_address (rtx x, refers to a constant pool entry of an address (or the sum of it plus a constant), a short (16-bit signed) constant plus a register, the sum of two registers, or a register indirect, possibly with an - auto-increment. For DFmode and DImode with a constant plus register, - we must ensure that both words are addressable or PowerPC64 with offset - word aligned. + auto-increment. For DFmode, DDmode and DImode with a constant plus + register, we must ensure that both words are addressable or PowerPC64 + with offset word aligned. - For modes spanning multiple registers (DFmode in 32-bit GPRs, + For modes spanning multiple registers (DFmode and DDmode in 32-bit GPRs, 32-bit DImode, TImode, TFmode, TDmode), indexed addressing cannot be used because adjacent memory cells are accessed by adding word-sized offsets during assembly output. */ @@ -4118,8 +4126,8 @@ rs6000_legitimate_address (enum machine_ && mode != TFmode && mode != TDmode /* Restrict addressing for DI because of our SUBREG hackery. */ - && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode - || mode == DImode)) + && !(TARGET_E500_DOUBLE + && (mode == DFmode || mode == DDmode || mode == DImode)) && TARGET_UPDATE && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)) return 1; @@ -4142,7 +4150,7 @@ rs6000_legitimate_address (enum machine_ && mode != TDmode && ((TARGET_HARD_FLOAT && TARGET_FPRS) || TARGET_POWERPC64 - || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode)) + || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE)) && (TARGET_POWERPC64 || mode != DImode) && legitimate_indexed_address_p (x, reg_ok_strict)) return 1; @@ -4152,12 +4160,13 @@ rs6000_legitimate_address (enum machine_ && mode != TDmode && ((TARGET_HARD_FLOAT && TARGET_FPRS) || TARGET_POWERPC64 - || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode)) + || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE)) && (TARGET_POWERPC64 || mode != DImode) && !ALTIVEC_VECTOR_MODE (mode) && !SPE_VECTOR_MODE (mode) /* Restrict addressing for DI because of our SUBREG hackery. */ - && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode)) + && !(TARGET_E500_DOUBLE + && (mode == DFmode || mode == DDmode || mode == DImode)) && TARGET_UPDATE && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict) && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict) @@ -5407,7 +5416,8 @@ function_arg_advance (CUMULATIVE_ARGS *c else { cum->fregno = FP_ARG_V4_MAX_REG + 1; - if (mode == DFmode || mode == TFmode || mode == DDmode || mode == TDmode) + if (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode) cum->words += cum->words & 1; cum->words += rs6000_arg_size (mode, type); } @@ -5490,12 +5500,14 @@ spe_build_register_parallel (enum machin switch (mode) { case DFmode: + case DDmode: r1 = gen_rtx_REG (DImode, gregno); r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx); return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1)); case DCmode: case TFmode: + case TDmode: r1 = gen_rtx_REG (DImode, gregno); r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx); r3 = gen_rtx_REG (DImode, gregno + 2); @@ -5527,13 +5539,14 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS /* On E500 v2, double arithmetic is done on the full 64-bit GPR, but are passed and returned in a pair of GPRs for ABI compatibility. */ - if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DCmode - || mode == TFmode || mode == TCmode)) + if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode + || mode == DCmode || mode == TCmode)) { int n_words = rs6000_arg_size (mode, type); /* Doubles go in an odd/even register pair (r5/r6, etc). */ - if (mode == DFmode) + if (mode == DFmode || mode == DDmode) gregno += (1 - gregno) & 1; /* Multi-reg args are not split between registers and stack. */ @@ -13718,8 +13731,8 @@ rs6000_split_multireg_move (rtx dst, rtx reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode; else if (ALTIVEC_REGNO_P (reg)) reg_mode = V16QImode; - else if (TARGET_E500_DOUBLE && mode == TFmode) - reg_mode = DFmode; + else if (TARGET_E500_DOUBLE && (mode == TFmode || mode == TDmode)) + reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode; else reg_mode = word_mode; reg_mode_size = GET_MODE_SIZE (reg_mode); @@ -14458,7 +14471,8 @@ spe_func_has_64bit_regs_p (void) if (SPE_VECTOR_MODE (mode)) return true; - if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode)) + if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode)) return true; } } @@ -15274,7 +15288,7 @@ emit_frame_save (rtx frame_reg, rtx fram /* Some cases that need register indexed addressing. */ if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) - || (TARGET_E500_DOUBLE && mode == DFmode) + || (TARGET_E500_DOUBLE && (mode == DFmode || mode == DDmode)) || (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode) && !SPE_CONST_OFFSET_OK (offset))) @@ -15314,7 +15328,7 @@ gen_frame_mem_offset (enum machine_mode int_rtx = GEN_INT (offset); if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode)) - || (TARGET_E500_DOUBLE && mode == DFmode)) + || (TARGET_E500_DOUBLE && (mode == DFmode || mode == DDmode))) { offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH); emit_move_insn (offset_rtx, int_rtx); @@ -21521,8 +21535,8 @@ rs6000_function_value (const_tree valtyp && ALTIVEC_VECTOR_MODE (mode)) regno = ALTIVEC_ARG_RETURN; else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT - && (mode == DFmode || mode == DCmode - || mode == TFmode || mode == TCmode)) + && (mode == DFmode || mode == DDmode || mode == DCmode + || mode == TFmode || mode == TDmode || mode == TCmode)) return spe_build_register_parallel (mode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; @@ -21583,8 +21597,8 @@ rs6000_libcall_value (enum machine_mode else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg) return rs6000_complex_function_value (mode); else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT - && (mode == DFmode || mode == DCmode - || mode == TFmode || mode == TCmode)) + && (mode == DFmode || mode == DDmode || mode == DCmode + || mode == TFmode || mode == TDmode || mode == TCmode)) return spe_build_register_parallel (mode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; @@ -21642,7 +21656,8 @@ rs6000_dwarf_register_span (rtx reg) if (TARGET_SPE && (SPE_VECTOR_MODE (GET_MODE (reg)) - || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode))) + || (TARGET_E500_DOUBLE + && (GET_MODE (reg) == DFmode || GET_MODE (reg) == DDmode)))) ; else return NULL_RTX; Index: config/rs6000/rs6000.h =================================================================== --- config/rs6000/rs6000.h (revision 129901) +++ config/rs6000/rs6000.h (working copy) @@ -559,7 +559,8 @@ extern enum rs6000_nop_insertion rs6000_ that the object would ordinarily have. */ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \ - (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \ + (TARGET_E500_DOUBLE \ + && (TYPE_MODE (TYPE) == DFmode || TYPE_MODE (TYPE) == DDmode)) ? 64 : \ ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \ && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \ && TREE_CODE (TYPE) == VECTOR_TYPE \ @@ -585,7 +586,7 @@ extern enum rs6000_nop_insertion rs6000_ fit into 1, whereas DI still needs two. */ #define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \ ((TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE) \ - || (TARGET_E500_DOUBLE && (MODE) == DFmode)) + || (TARGET_E500_DOUBLE && ((MODE) == DFmode || (MODE) == DDmode))) /* A bit-field declared as `int' forces `int' alignment for the struct. */ #define PCC_BITFIELD_TYPE_MATTERS 1 @@ -604,7 +605,8 @@ extern enum rs6000_nop_insertion rs6000_ #define DATA_ALIGNMENT(TYPE, ALIGN) \ (TREE_CODE (TYPE) == VECTOR_TYPE ? ((TARGET_SPE_ABI \ || TARGET_PAIRED_FLOAT) ? 64 : 128) \ - : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \ + : (TARGET_E500_DOUBLE \ + && (TYPE_MODE (TYPE) == DFmode || TYPE_MODE (TYPE) == DDmode)) ? 64 \ : TREE_CODE (TYPE) == ARRAY_TYPE \ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) @@ -1178,7 +1180,8 @@ enum reg_class #define CLASS_MAX_NREGS(CLASS, MODE) \ (((CLASS) == FLOAT_REGS) \ ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \ - : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS && (MODE) == DFmode) \ + : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS \ + && ((MODE) == DFmode || (MODE) == DDmode)) \ ? 1 \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) @@ -1192,6 +1195,8 @@ enum reg_class : (((TARGET_E500_DOUBLE \ && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \ || (((TO) == TFmode) + ((FROM) == TFmode)) == 1 \ + || (((TO) == DDmode) + ((FROM) == DDmode)) == 1 \ + || (((TO) == TDmode) + ((FROM) == TDmode)) == 1 \ || (((TO) == DImode) + ((FROM) == DImode)) == 1)) \ || (TARGET_SPE \ && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1)) \ @@ -1717,11 +1722,11 @@ typedef struct rs6000_args refers to a constant pool entry of an address (or the sum of it plus a constant), a short (16-bit signed) constant plus a register, the sum of two registers, or a register indirect, possibly with an - auto-increment. For DFmode and DImode with a constant plus register, - we must ensure that both words are addressable or PowerPC64 with offset - word aligned. + auto-increment. For DFmode, DDmode and DImode with a constant plus + register, we must ensure that both words are addressable or PowerPC64 + with offset word aligned. - For modes spanning multiple registers (DFmode in 32-bit GPRs, + For modes spanning multiple registers (DFmode and DDmode in 32-bit GPRs, 32-bit DImode, TImode), indexed addressing cannot be used because adjacent memory cells are accessed by adding word-sized offsets during assembly output. */ Index: gcc.dg/dfp/ddmode-ice.c =================================================================== --- gcc.dg/dfp/ddmode-ice.c (revision 0) +++ gcc.dg/dfp/ddmode-ice.c (revision 0) @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99 -O1" } */ + +/* This used to result in an ICE. */ + +_Decimal64 y[258][258]; +_Decimal64 dd[258][258]; +_Decimal64 ry[258][258]; +_Decimal64 +foo (void) +{ + int i; + int j; + int m; + int im; + int jm; + int ip; + int jp; + int i2m; + int i1p; + _Decimal64 a; + _Decimal64 b; + _Decimal64 c; + _Decimal64 qi; + _Decimal64 qj; + _Decimal64 xx; + _Decimal64 yx; + _Decimal64 xy; + _Decimal64 yy; + _Decimal64 rel; + _Decimal64 qxx; + _Decimal64 qyy; + _Decimal64 qxy; + do + { + jp = j + 1; + for (i = i1p; i <= i2m; i++) + { + ip = i + 1; + yx = y[ip][j] - y[im][j]; + yy = y[i][jp] - y[i][jm]; + a = 0.25dd * (xy * xy + yy * yy); + b = 0.25dd * (xx * xx + yx * yx); + c = 0.125dd * (xx * xy + yx * yy); + qj = 0.0dd; + dd[i][m] = b + a * rel + b; + qxx = y[ip][j] - 2.0dd * y[i][j] + y[im][j]; + qyy = y[i][jp] - 2.0dd * y[i][j] + y[i][jm]; + qxy = y[ip][jp] - y[ip][jm] - y[im][jp] + y[im][jm]; + ry[i][m] = a * qxx + b * qyy - c * qxy + yx * qi + yy * qj; + } + } + while (1); +}