From patchwork Tue May 22 23:24:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 918604 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-478215-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="JcUconl+"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40rBZK5qJTz9s1d for ; Wed, 23 May 2018 09:24:55 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:mime-version:content-type:message-id; q=dns; s=default; b=wt2tcuSnL+scc8Xk9GnnYMgu4K9T1awzIacf9EbkSRxPAGhawo uWa0/cexOk/c+3vS/m5MqQTT+jDkLSV+YT3dduZy8XsEnoH76EAO0f46eFs+CBxL ncrUsDIQIbiyr+Uu6WRJPql9xEHEaYZtiw8jkV88z9nGwYSMurngdv3ks= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:mime-version:content-type:message-id; s= default; bh=RdARd0FwyRru8jW+XIVc7TlGNZE=; b=JcUconl+/zC781vUfaVm B5Ein8L3a599dB44sx2rKlAGPkpdTZQ7CAZmwFv+haMvJce5GpEgeopieJiB1Jpb GcEt//LOKcs0EepYRVVrPcXpwxyzbm7jmfDBizjMsJEYTX5lxwmjifPrmCP1OnGN zPbwEn9dxbKuy60ucE/Oc3c= Received: (qmail 130487 invoked by alias); 22 May 2018 23:24:45 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 130318 invoked by uid 89); 22 May 2018 23:24:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_MANYTO, KAM_SHORT, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=HTo:D*fr X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 22 May 2018 23:24:26 +0000 Received: from pps.filterd (m0098417.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w4MNON9o061133 for ; Tue, 22 May 2018 19:24:24 -0400 Received: from e34.co.us.ibm.com (e34.co.us.ibm.com [32.97.110.152]) by mx0a-001b2d01.pphosted.com with ESMTP id 2j4tsbc74g-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 22 May 2018 19:24:23 -0400 Received: from localhost by e34.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 22 May 2018 17:24:23 -0600 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e34.co.us.ibm.com (192.168.1.134) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 22 May 2018 17:24:20 -0600 Received: from b03ledav003.gho.boulder.ibm.com (b03ledav003.gho.boulder.ibm.com [9.17.130.234]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w4MNOJ5e7340380 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 22 May 2018 16:24:19 -0700 Received: from b03ledav003.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7299B6A03C; Tue, 22 May 2018 17:24:19 -0600 (MDT) Received: from ibm-toto.the-meissners.org (unknown [9.32.77.218]) by b03ledav003.gho.boulder.ibm.com (Postfix) with ESMTPS id 896456A03B; Tue, 22 May 2018 17:24:18 -0600 (MDT) Date: Tue, 22 May 2018 19:24:16 -0400 From: Michael Meissner To: GCC Patches , Segher Boessenkool , David Edelsohn , Bill Schmidt , Michael Meissner , =?iso-8859-1?q?Fran=E7ois?= Dumont , Jeff Law , Eric Botcazou , Joseph Myers Cc: Richard Biener , Jakub Jelinek Subject: [PATCH] PR target/85358: Add target hook to prevent default widening Mail-Followup-To: Michael Meissner , GCC Patches , Segher Boessenkool , David Edelsohn , Bill Schmidt , =?iso-8859-1?q?Fran=E7ois?= Dumont , Jeff Law , Eric Botcazou , Joseph Myers , Richard Biener , Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-TM-AS-GCONF: 00 x-cbid: 18052223-0016-0000-0000-000008C7DFA8 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00009068; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000261; SDB=6.01036221; UDB=6.00530080; IPR=6.00815349; MB=3.00021247; MTD=3.00000008; XFM=3.00000015; UTC=2018-05-22 23:24:22 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18052223-0017-0000-0000-00003EDAA6E8 Message-Id: <20180522232416.GA20583@ibm-toto.the-meissners.org> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-22_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=8 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1805220232 I posted this patch at the end of GCC 8 as a RFC. Now that we are in GCC 9, I would like to repose it. Sorry to spam some of you. It is unclear whom the reviewers for things like target hooks and basic mode handling are. Here is the original patch. https://gcc.gnu.org/ml/gcc-patches/2018-04/msg00764.html PowerPC has 3 different 128-bit floating point types (KFmode, IFmode, and TFmode). We are in the process of migrating long double from IBM extended double to IEEE 128-bit floating point. * IFmode is IBM extended double (__ibm128) * KFmode is IEEE 128-bit floating point (__float128, _Float128N) * TFmode is whatever long double maps to If we are compiling for a power8 system (which does not have hardware IEEE 128-bit floating point), the current system works because each of the 3 modes do not have hardware support. If we are compiling for a power9 system and long double is IBM extended double, again things are fine. However, if we compiling for power9 and we've flipped the default for long double to be IEEE 128-bit floating point, then the code to support __ibm128 breaks. The machine independent portions of the mode handling says oh, there is hardware to support TFmode operations, lets widen the type to TFmode and do those operations. However, converting IFmode to TFmode is not cheap, it has to be done in a function call. This patch adds a new target hook, that if it is overriden, the backend can say don't automatically widen this type to that type. The PowerPC port defines the target hook so that it doesn't automatically convert IBM extended double to IEEE 128-bit and vice versa. This patch goes through all of the places that calls GET_MODE_WIDER_MODE and then calls the target hook. Now, the PowerPC only needs to block certain floating point widenings. Several of the changes are to integer widenings, and if desired, we could restrict the changes to just floating point types. However, there might be other ports that need the flexibility for other types. I have tried various other approprches to fix this problem, and so far, I have not been able to come up with a PowerPC back-end only solution that works. Alternatively, Segher has suggested that the call to the target hook be in GET_MODE_WIDER_MODE and GET_MODE_2XWIDER_MODE (plus any places where we access the mode_wider array direcly). I have built little endian PowerPC builds with this patch, and I have verified that it does work. I have tested the same patch in April on a big endian PowerPC system and x86_64 and it worked there also. Can I check in this patch as is (I will verify x86/PowerPC big endian still works before checkin). Or would people prefer modifications to the patch? [gcc] 2018-05-22 Michael Meissner PR target/85358 * target.def (default_widening_p): New target hook to say whether default widening between modes should be done. * targhooks.h (hook_bool_mode_mode_bool_true): New declaration. * targhooks.c (hook_bool_mode_mode_bool_true): New default target hook. * optabs.c (expand_binop): Before doing default widening, check whether the backend allows the widening. (expand_twoval_unop): Likewise. (expand_twoval_binop): Likewise. (widen_leading): Likewise. (widen_bswap): Likewise. (expand_unop): Likewise. * cse.c (cse_insn): Likewise. * combine.c (simplify_comparison): Likewise. * var-tracking.c (prepare_call_arguments): Likewise. * config/rs6000/rs6000.c (TARGET_DEFAULT_WIDENING_P): Define target hook to prevent IBM extended double and IEEE 128-bit floating point from being converted to each by default. (rs6000_default_widening_p): Likewise. * doc/tm.texi (TARGET_DEFAULT_WIDENING_P): Document the new default widening hook. * doc/tm.texi.in (TARGET_DEFAULT_WIDENING_P): Likewise. [gcc/testsuite] 2018-05-22 Michael Meissner PR target/85358 * gcc.target/powerpc/pr85358.c: New test to make sure __ibm128 does not widen to __float128 on ISA 3.0 systems. In order to start the transition of PowerPC long double to IEEE 128-bit, we will need this patch or a similar patch to be back ported to GCC 8.2. Index: gcc/target.def =================================================================== --- gcc/target.def (revision 260550) +++ gcc/target.def (working copy) @@ -3498,6 +3498,13 @@ If this hook allows @code{val} to have a hook_bool_mode_uhwi_false) DEFHOOK +(default_widening_p, + "Return true if GCC can automatically widen from @var{from_mode} to\n\ +@var{to_mode}. Conversions are unsigned if @var{unsigned_p} is true.", + bool, (machine_mode, machine_mode, bool), + hook_bool_mode_mode_bool_true) + +DEFHOOK (libgcc_floating_mode_supported_p, "Define this to return nonzero if libgcc provides support for the \n\ floating-point mode @var{mode}, which is known to pass \n\ Index: gcc/targhooks.c =================================================================== --- gcc/targhooks.c (revision 260550) +++ gcc/targhooks.c (working copy) @@ -2345,4 +2345,12 @@ default_select_early_remat_modes (sbitma { } +bool +hook_bool_mode_mode_bool_true (machine_mode from_mode ATTRIBUTE_UNUSED, + machine_mode to_mode ATTRIBUTE_UNUSED, + bool unsigned_p ATTRIBUTE_UNUSED) +{ + return true; +} + #include "gt-targhooks.h" Index: gcc/targhooks.h =================================================================== --- gcc/targhooks.h (revision 260550) +++ gcc/targhooks.h (working copy) @@ -289,5 +289,6 @@ extern enum flt_eval_method default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED); extern bool default_stack_clash_protection_final_dynamic_probe (rtx); extern void default_select_early_remat_modes (sbitmap); +extern bool hook_bool_mode_mode_bool_true (machine_mode, machine_mode, bool); #endif /* GCC_TARGHOOKS_H */ Index: gcc/optabs.c =================================================================== --- gcc/optabs.c (revision 260550) +++ gcc/optabs.c (working copy) @@ -1284,14 +1284,15 @@ expand_binop (machine_mode mode, optab b FOR_EACH_WIDER_MODE (wider_mode, mode) { machine_mode next_mode; - if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing - || (binoptab == smul_optab - && GET_MODE_WIDER_MODE (wider_mode).exists (&next_mode) - && (find_widening_optab_handler ((unsignedp - ? umul_widen_optab - : smul_widen_optab), - next_mode, mode) - != CODE_FOR_nothing))) + if ((optab_handler (binoptab, wider_mode) != CODE_FOR_nothing + || (binoptab == smul_optab + && GET_MODE_WIDER_MODE (wider_mode).exists (&next_mode) + && (find_widening_optab_handler ((unsignedp + ? umul_widen_optab + : smul_widen_optab), + next_mode, mode) + != CODE_FOR_nothing))) + && targetm.default_widening_p (mode, wider_mode, unsignedp)) { rtx xop0 = op0, xop1 = op1; int no_extend = 0; @@ -1834,9 +1835,10 @@ expand_binop (machine_mode mode, optab b gcc_assert (!convert_optab_p (binoptab)); FOR_EACH_WIDER_MODE (wider_mode, mode) { - if (optab_handler (binoptab, wider_mode) - || (methods == OPTAB_LIB - && optab_libfunc (binoptab, wider_mode))) + if ((optab_handler (binoptab, wider_mode) + || (methods == OPTAB_LIB + && optab_libfunc (binoptab, wider_mode))) + && targetm.default_widening_p (mode, wider_mode, unsignedp)) { rtx xop0 = op0, xop1 = op1; int no_extend = 0; @@ -1989,7 +1991,8 @@ expand_twoval_unop (optab unoptab, rtx o { FOR_EACH_WIDER_MODE (wider_mode, mode) { - if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) + if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing + && targetm.default_widening_p (mode, wider_mode, unsignedp)) { rtx t0 = gen_reg_rtx (wider_mode); rtx t1 = gen_reg_rtx (wider_mode); @@ -2070,7 +2073,8 @@ expand_twoval_binop (optab binoptab, rtx { FOR_EACH_WIDER_MODE (wider_mode, mode) { - if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing) + if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing + && targetm.default_widening_p (mode, wider_mode, unsignedp)) { rtx t0 = gen_reg_rtx (wider_mode); rtx t1 = gen_reg_rtx (wider_mode); @@ -2169,7 +2173,9 @@ widen_leading (scalar_int_mode mode, rtx FOR_EACH_WIDER_MODE (wider_mode_iter, mode) { scalar_int_mode wider_mode = wider_mode_iter.require (); - if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) + bool unsignedp = unoptab != clrsb_optab; + if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing + && targetm.default_widening_p (mode, wider_mode, unsignedp)) { rtx xop0, temp; rtx_insn *last; @@ -2178,10 +2184,8 @@ widen_leading (scalar_int_mode mode, rtx if (target == 0) target = gen_reg_rtx (mode); - xop0 = widen_operand (op0, wider_mode, mode, - unoptab != clrsb_optab, false); - temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, - unoptab != clrsb_optab); + xop0 = widen_operand (op0, wider_mode, mode, unsignedp, false); + temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, unsignedp); if (temp != 0) temp = expand_binop (wider_mode, sub_optab, temp, @@ -2333,9 +2337,12 @@ widen_bswap (scalar_int_mode mode, rtx o opt_scalar_int_mode wider_mode_iter; FOR_EACH_WIDER_MODE (wider_mode_iter, mode) - if (optab_handler (bswap_optab, wider_mode_iter.require ()) - != CODE_FOR_nothing) - break; + { + machine_mode wider_mode = wider_mode_iter.require (); + if (optab_handler (bswap_optab, wider_mode) != CODE_FOR_nothing + && targetm.default_widening_p (mode, wider_mode, true)) + break; + } if (!wider_mode_iter.exists ()) return NULL_RTX; @@ -2865,7 +2872,8 @@ expand_unop (machine_mode mode, optab un if (CLASS_HAS_WIDER_MODES_P (mclass)) FOR_EACH_WIDER_MODE (wider_mode, mode) { - if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) + if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing + && targetm.default_widening_p (mode, wider_mode, unsignedp)) { rtx xop0 = op0; rtx_insn *last = get_last_insn (); @@ -3032,8 +3040,9 @@ expand_unop (machine_mode mode, optab un { FOR_EACH_WIDER_MODE (wider_mode, mode) { - if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing - || optab_libfunc (unoptab, wider_mode)) + if ((optab_handler (unoptab, wider_mode) != CODE_FOR_nothing + || optab_libfunc (unoptab, wider_mode)) + && targetm.default_widening_p (mode, wider_mode, unsignedp)) { rtx xop0 = op0; rtx_insn *last = get_last_insn (); Index: gcc/cse.c =================================================================== --- gcc/cse.c (revision 260550) +++ gcc/cse.c (working copy) @@ -4885,6 +4885,9 @@ cse_insn (rtx_insn *insn) if (GET_MODE_PRECISION (wider_mode) > BITS_PER_WORD) break; + if (!targetm.default_widening_p (mode, wider_mode, false)) + continue; + struct table_elt *const_elt = lookup (src_const, HASH (src_const, wider_mode), wider_mode); @@ -4924,6 +4927,9 @@ cse_insn (rtx_insn *insn) if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD) break; + if (!targetm.default_widening_p (mode, tmode, false)) + continue; + rtx inner = gen_lowpart (tmode, XEXP (src, 0)); struct table_elt *larger_elt; @@ -4979,6 +4985,9 @@ cse_insn (rtx_insn *insn) if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD) break; + if (!targetm.default_widening_p (mode, tmode, false)) + continue; + PUT_MODE (memory_extend_rtx, tmode); larger_elt = lookup (memory_extend_rtx, HASH (memory_extend_rtx, tmode), tmode); Index: gcc/combine.c =================================================================== --- gcc/combine.c (revision 260550) +++ gcc/combine.c (working copy) @@ -12965,6 +12965,9 @@ simplify_comparison (enum rtx_code code, || (nonzero_bits (op1, tmode) & ~GET_MODE_MASK (mode)) == 0))); + if (!targetm.default_widening_p (mode, tmode, zero_extended)) + continue; + if (zero_extended || ((num_sign_bit_copies (op0, tmode) > (unsigned int) (GET_MODE_PRECISION (tmode) Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c (revision 260550) +++ gcc/var-tracking.c (working copy) @@ -6347,10 +6347,14 @@ prepare_call_arguments (basic_block bb, opt_scalar_int_mode mode_iter; FOR_EACH_WIDER_MODE (mode_iter, mode) { + machine_mode old_mode = mode; mode = mode_iter.require (); if (GET_MODE_BITSIZE (mode) > BITS_PER_WORD) break; + if (!targetm.default_widening_p (old_mode, mode, false)) + continue; + rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0); if (reg == NULL_RTX || !REG_P (reg)) continue; Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 260552) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1973,6 +1973,9 @@ static const struct attribute_spec rs600 #undef TARGET_STARTING_FRAME_OFFSET #define TARGET_STARTING_FRAME_OFFSET rs6000_starting_frame_offset + +#undef TARGET_DEFAULT_WIDENING_P +#define TARGET_DEFAULT_WIDENING_P rs6000_default_widening_p /* Processor table. */ @@ -16502,6 +16505,29 @@ rs6000_init_builtins (void) #endif } +/* Return true if FROM_MODE can be widened to TO_MODE automatically. UNSIGNEDP + says the conversion is unsigned. + + On PowerPC, don't allow IBM extended double to widen to an IEEE 128-bit + floating point value or vice versa. */ + +static bool +rs6000_default_widening_p (machine_mode from_mode, + machine_mode to_mode, + bool unsignedp ATTRIBUTE_UNUSED) +{ + if (!TARGET_FLOAT128_TYPE) + return true; + + if (FLOAT128_IEEE_P (from_mode) && FLOAT128_IBM_P (to_mode)) + return false; + + if (FLOAT128_IBM_P (from_mode) && FLOAT128_IEEE_P (to_mode)) + return false; + + return true; +} + /* Returns the rs6000 builtin decl for CODE. */ static tree Index: gcc/doc/tm.texi =================================================================== --- gcc/doc/tm.texi (revision 260550) +++ gcc/doc/tm.texi (working copy) @@ -4315,6 +4315,11 @@ If this hook allows @code{val} to have a @code{int8x8x3_t}s in registers rather than forcing them onto the stack. @end deftypefn +@deftypefn {Target Hook} bool TARGET_DEFAULT_WIDENING_P (machine_mode, @var{machine_mode}, @var{bool}) +Return true if GCC can automatically widen from @var{from_mode} to +@var{to_mode}. Conversions are unsigned if @var{unsigned_p} is true. +@end deftypefn + @deftypefn {Target Hook} bool TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P (scalar_float_mode @var{mode}) Define this to return nonzero if libgcc provides support for the floating-point mode @var{mode}, which is known to pass Index: gcc/doc/tm.texi.in =================================================================== --- gcc/doc/tm.texi.in (revision 260550) +++ gcc/doc/tm.texi.in (working copy) @@ -3344,6 +3344,8 @@ stack. @hook TARGET_ARRAY_MODE_SUPPORTED_P +@hook TARGET_DEFAULT_WIDENING_P + @hook TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P @hook TARGET_FLOATN_MODE Index: gcc/testsuite/gcc.target/powerpc/pr85358.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr85358.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr85358.c (working copy) @@ -0,0 +1,14 @@ +/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-vector -mfloat128 -O2 -mabi=ieeelongdouble -Wno-psabi" } */ + +/* Verify that __ibm128 does not get converted automatically to IEEE 128-bit on + machines with IEEE 128-bit hardware support. */ + +__ibm128 +add (__ibm128 a, __ibm128 b) +{ + return a + b; +} + +/* { dg-final { scan-assembler-not {\mxsaddqp\M} } } */