From patchwork Tue Aug 30 09:00:00 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 664059 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3sNjCN4D94z9s9G for ; Tue, 30 Aug 2016 19:00:15 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=aOSGL8ir; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:cc:content-type; q=dns; s=default; b=yQQCVBCgMrkr7+os/ojVbwRphdYsPgBdbzTuzYTrcOm g2D5QDqGIJ2Y8tQAEFUMqPfV/7+JTiljUKpGrUA6M6mNtdzpJoAepBeJnnoYkA8Z ray4IZk47Y/rpnnQodcneGDslGQe80/0F4y2kqDEOfFlS1y6nWjE8frfcb6Dev9E = 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 :mime-version:from:date:message-id:subject:to:cc:content-type; s=default; bh=C19APLtQ+VOnwKWiwxaAgPeXH4s=; b=aOSGL8irUjXn66MCv NxY2yH8C7GG8c8dTozVibQJaGl29pISLIgy8IiSFr8FdQ8+Yj7rlFYlVvJplTCyc yIrsFOPZx7bPTmMrE3pvVteeEOrI9treaCu1CrNavnDxXrNpdcKDA4i/vaRmUqud auR39rJ3+Rr9Llr6mYchZKck8o= Received: (qmail 37653 invoked by alias); 30 Aug 2016 09:00:07 -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 37598 invoked by uid 89); 30 Aug 2016 09:00:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=$30, $26, 1c, UD:alpha.c X-HELO: mail-ua0-f170.google.com Received: from mail-ua0-f170.google.com (HELO mail-ua0-f170.google.com) (209.85.217.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 30 Aug 2016 09:00:03 +0000 Received: by mail-ua0-f170.google.com with SMTP id m60so21423526uam.3 for ; Tue, 30 Aug 2016 02:00:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=eB0AnbpVWkoO2LE+lP3cNnxC5VjE7LTTv+04op+P1CY=; b=g44tPr3rSTb4mK5ko7tgE0ElEdDakXhDwTMAJ6n12sXJ3mIhQTyJOoZ3Eob9FSQFIS 9x26tYfr+U+nEllKtuSfJpgz6XLuRjVmsLlOpziKQ0NeAnl9Vhu7dxcsjVS2VVF6RXkR /6H9KfwTD1uJUuksKWC0Eb0I7+3KiNhhy4tJnqRUA7noUrNIJMxvV84tVO1ygj5ZFhDX PpPoX3bbBKlmxodXSBHG4TOYotLlSkm/aiBo1PnX6YIkWzZTNorMisJjB7mkoHVyxF1e r/GW20Mdh5lIWKr16Jl5+0SZHGyedll9cJF5+YOqRaUOHQisa4jferwGPVE0vL6X+g3x M7mA== X-Gm-Message-State: AE9vXwO0qCDrIDSZ5kHvdCmpYYOvUIk6gUU8WM0N622uu6Wwhn/7aopvBvZQ3fueDn8FIIdPIquN3hUaqD6miQ== X-Received: by 10.31.134.195 with SMTP id i186mr1504659vkd.21.1472547601562; Tue, 30 Aug 2016 02:00:01 -0700 (PDT) MIME-Version: 1.0 Received: by 10.103.21.134 with HTTP; Tue, 30 Aug 2016 02:00:00 -0700 (PDT) From: Uros Bizjak Date: Tue, 30 Aug 2016 11:00:00 +0200 Message-ID: Subject: [RFC PATCH, alpha]: Disable _FloatN on alpha To: "gcc-patches@gcc.gnu.org" Cc: Richard Henderson , "Joseph S. Myers" Hello! The _FloatN patch uncovers a problem on alpha OSF/1 ABI when _Float32 variable arguments are passed to a function. As seen from the source, 32bit _Float32 arguments (SFmode) are *not* promoted to 64bit DFmode when passing to as variable arguments, and this uncovers following limitation: Values, passed in FP registers are pushed to a pretend-args area of called va-arg function in their 64-bit full word mode, so they are stored as their bit-exact copy from the reg to the memory using STT instruction. However, when this memory is later accessed as SFmode value using LDS instruction, this doesn't load SFmode value (as it was passed in the FP register), since LDS reorders bits on the way from/to memory. To make things worse, the value can be moved from pretend-args area as a DImode value and stored as a SImode subreg of this value. Float arguments, passed to va-arg function work OK, since default c promoting rules always promote float variable arguments to double. This is not the case with _Float32. To illustrate the problem, consider following source: --cut here-- volatile _Float32 a = 1.0f32, b = 2.5F32, c = -2.5f32; _Float32 vafn (_Float32 arg1, ...) { __builtin_va_list ap; _Float32 ret; __builtin_va_start (ap, arg1); ret = arg1 + __builtin_va_arg (ap, _Float32); __builtin_va_end (ap); return ret; } int main (void) { volatile _Float32 r; r = vafn (a, c); if (r != -1.5f32) __builtin_abort (); return 0; } --cut here-- Please note the lack of promotion in __builtin_va_arg. This is compiled to following assembly: vafn: ... stt $f17,24($30) <- store DFmode to pretend args area and ... ldq $1,24($30) <- ... load it as DImode value ... stl $1,16($30) <- store SImode subreg to stack and ... lds $f10,16($30) <- ... load it as SFmode value stq $1,40($30) <- (dead DImode store) adds $f16,$f10,$f0 <- use SFmode value in $f10 ... main: ... lda $1,a lds $f16,0($1) lda $1,c lds $f17,0($1) jsr $26,vafn ... SFmode values are stored in the FP registers in canonical form, as subset of DFmode values, with 11-bit exponents restricted to the corresponding single-precision range, and with the 29 low-order fraction bits restricted to be all zero. IOW, it is not possible to load SFmode value from the location where the full 64bit value was stored from the FP register. I didn't find a way around this limitation, so I propose to disable _FloatN on alpha with the attached patch. Uros. diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 702cd27..1bf27ca 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -736,6 +736,20 @@ alpha_vector_mode_supported_p (machine_mode mode) return mode == V8QImode || mode == V4HImode || mode == V2SImode; } +/* Target hook for floatn_mode. */ + +static machine_mode +alpha_floatn_mode (int n ATTRIBUTE_UNUSED, bool extended ATTRIBUTE_UNUSED) +{ + /* Alpha can't pass _Float32 variable arguments. The function that is + receiving a variable number of arguments pushes floating-point values + in the remaining incoming registers to the stack as DFmode 64-bit values. + These stores are not compatible with SFmode loads due to implicit + reordering of bits during SFmode load. Disable all _Floatn types. */ + + return VOIDmode; +} + /* Return 1 if this function can directly return via $26. */ int @@ -9978,8 +9992,6 @@ alpha_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) #undef TARGET_PROMOTE_FUNCTION_MODE #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false #undef TARGET_FUNCTION_VALUE #define TARGET_FUNCTION_VALUE alpha_function_value @@ -10020,6 +10032,8 @@ alpha_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) #define TARGET_SCALAR_MODE_SUPPORTED_P alpha_scalar_mode_supported_p #undef TARGET_VECTOR_MODE_SUPPORTED_P #define TARGET_VECTOR_MODE_SUPPORTED_P alpha_vector_mode_supported_p +#undef TARGET_FLOATN_MODE +#define TARGET_FLOATN_MODE alpha_floatn_mode #undef TARGET_BUILD_BUILTIN_VA_LIST #define TARGET_BUILD_BUILTIN_VA_LIST alpha_build_builtin_va_list