From patchwork Sun Jan 6 22:59:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 1021119 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-493487-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="DrjfuCYN"; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fIxMNmuK"; 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 43Xv9R1svkz9sCX for ; Mon, 7 Jan 2019 09:59:38 +1100 (AEDT) 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:message-id:mime-version:content-type; q=dns; s=default; b=HDzyZBxYOKlJX66+cW49eEGCX0yXbHlbnsJ7uqiyitBsYWEDUo 3qtOTDA+BwIC26lOITEby8w2YBI5h7BKCmkFFu8jlSNhZIQsMZGAj+V4wKFioRNG JqCt6FoLHCVpWhsmBu3cQ0MG5QojLCmWz4wAOIUrtgcx93RgcRkAtlu/0= 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:message-id:mime-version:content-type; s= default; bh=VsRK4wvxAVeYva3CSKJ3Q8BUcaA=; b=DrjfuCYNde6NcjvhcPhv o8PoYs2sAnF1MveZchdmWhaYjs8NUhI1eTXm5K+yNTQfC2Lp2PT/gItGJjHqHhqx feFj+iMq+86jAzZIFkSKZkwXtkwtp2Gntysm5wBh1Db7fVuagqBzCsU4Ywrg6hbA nSTJoPtvUezXtPDdwi41efw= Received: (qmail 60606 invoked by alias); 6 Jan 2019 22:59:30 -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 60589 invoked by uid 89); 6 Jan 2019 22:59:30 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.4 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=ss, progress, HX-Received:1444, prevent X-HELO: mail-pf1-f173.google.com Received: from mail-pf1-f173.google.com (HELO mail-pf1-f173.google.com) (209.85.210.173) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 06 Jan 2019 22:59:25 +0000 Received: by mail-pf1-f173.google.com with SMTP id b7so20877606pfi.8 for ; Sun, 06 Jan 2019 14:59:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=E/rrwlJ2lzYUrlHsewK0XpHbeRWY8ijhDN1Q3+dNaKg=; b=fIxMNmuKjgUDFB1S+zisbzGxnybqzTA3dSxZgtLJpJACxMkissBTLxEljbvHHjIRvc c5L105D+Q6vJD8dbPjhQ2ZOrGN5DcVHG7omL2IyBomEvbbJ/5SuIX7tJiKYp5grvH5+k xKlGuECn+o3aQDIMZB+q/ar9o106RmeiMDHLi0cMPv+keCAfaSrCQuaNU/GXV8+p7x/b +oqULO4vSZ/W79LL2/P+beJHmvjkdq75/1yUurZrnALxdy2GwihEFLIf5idqWr9WsP1Q Ufj4c1w0kcgNcAQpERxEyy9AK3ppBu+TtXdyVrGfettALFFThpaBslo7bdbABBZO1fJt swWQ== Received: from bubble.grove.modra.org ([58.175.241.133]) by smtp.gmail.com with ESMTPSA id n21sm93488157pfg.84.2019.01.06.14.59.21 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 06 Jan 2019 14:59:22 -0800 (PST) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id E7CE9805F0; Mon, 7 Jan 2019 09:29:18 +1030 (ACDT) Date: Mon, 7 Jan 2019 09:29:18 +1030 From: Alan Modra To: gcc-patches@gcc.gnu.org Cc: Segher Boessenkool Subject: [RS6000] PR88614, output_operand: invalid %z value Message-ID: <20190106225918.GG3170@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.4 (2018-02-28) X-IsSubscribed: yes The direct cause of this PR is the fact that tls_gdld_nomark didn't handle indirect calls. Adding the missing support revealed that most indirect calls were being optimised back to direct calls anyway, due to tls_gdld_nomark not checking any of the parallel elements except the first (plus the extra element that distinguishes this call from normal calls). Just checking the number of elements is enough to separate the indirect calls from direct for ABI_ELFv2 and ABI_AIX, while checking for the LONG_CALL bit in the cookie works for ABI_V4. Direct calls being substituted for indirect calls is not the only unwanted substitution. See the tls_nomark_call comment. I also saw a _GLOBAL_OFFSET_TABLE_ symbol_ref being substituted for the GOT reg, hence the unspec_tls change. Bootstrap and regression testing on powerpc64le-linux and powerpc64-linux in progress. Note that the patch requires https://gcc.gnu.org/ml/gcc-patches/2019-01/msg00252.html or the earlier version for the attribute support. PR 88614 * config/rs6000/predicates.md (unspec_tls): Ensure GOT reg stays a reg. (tls_nomark_call): New. * config/rs6000/rs6000.c (rs6000_call_sysv): Generate sysv4 secure plt call pattern here.. * config/rs6000/rs6000.md (call_nonlocal_sysv): ..rather than here, delete split.. (call_value_nonlocal_sysv): ..or here, delete split. (tls_gdld_nomark): Use tls_nomark_call predicate. Set up operands for indirect calls and correct length attr. diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 21791c51f2f..246452879a8 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -988,7 +988,12 @@ (define_predicate "rs6000_tls_symbol_ref" (define_predicate "unspec_tls" (match_code "unspec") { - return XINT (op, 1) == UNSPEC_TLSGD || XINT (op, 1) == UNSPEC_TLSLD; + if (XINT (op, 1) == UNSPEC_TLSGD) + return REG_P (XVECEXP (op, 0, 1)); + else if (XINT (op, 1) == UNSPEC_TLSLD) + return REG_P (XVECEXP (op, 0, 0)); + else + return 0; }) ;; Return 1 if the operand, used inside a MEM, is a valid first argument @@ -1018,6 +1023,86 @@ (define_predicate "indirect_call_operand" return false; }) +;; Verify that elements of the tls_gdld_nomark call insn parallel past the +;; second element (added to distinguish this call from normal calls) match +;; the normal contours of a call insn. This is necessary to prevent +;; substitutions we don't want, for example, an indirect call being +;; optimised to a direct call, or (set (reg:r2) (unspec [] UNSPEC_TOCSLOT)) +;; being cleverly optimised to (set (reg:r2) (reg:r2)) because gcc +;; "knows" that r2 hasn't changed from a previous call. +(define_predicate "tls_nomark_call" + (match_code "parallel") +{ + int n = XVECLEN (op, 0); + rtvec v = XVEC (op, 0); + rtx set = RTVEC_ELT (v, 0); + if (GET_CODE (set) != SET) + return 0; + rtx call = XEXP (set, 1); + if (GET_CODE (call) != CALL) + return 0; + rtx mem = XEXP (call, 0); + if (GET_CODE (mem) != MEM) + return 0; + rtx addr = XEXP (mem, 0); + if (GET_CODE (addr) == SYMBOL_REF) + { + if (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_AIX) + return (n == 3 && GET_CODE (RTVEC_ELT (v, 2)) == CLOBBER + && REG_P (XEXP (RTVEC_ELT (v, 2), 0)) + && REGNO (XEXP (RTVEC_ELT (v, 2), 0)) == LR_REGNO); + else if (DEFAULT_ABI == ABI_V4) + return (n >= 4 && n <= 5 && GET_CODE (RTVEC_ELT (v, 2)) == USE + && CONST_INT_P (XEXP (RTVEC_ELT (v, 2), 0)) + && (INTVAL (XEXP (RTVEC_ELT (v, 2), 0)) & CALL_LONG) == 0 + && (n == 4 + || (GET_CODE (RTVEC_ELT (v, 3)) == USE + && REG_P (XEXP (RTVEC_ELT (v, 3), 0)))) + && GET_CODE (RTVEC_ELT (v, n - 1)) == CLOBBER + && REG_P (XEXP (RTVEC_ELT (v, n - 1), 0)) + && REGNO (XEXP (RTVEC_ELT (v, n - 1), 0)) == LR_REGNO); + else + gcc_unreachable (); + } + else if (indirect_call_operand (addr, mode)) + { + if (DEFAULT_ABI == ABI_ELFv2) + return (n == 4 && GET_CODE (RTVEC_ELT (v, 2)) == SET + && REG_P (XEXP (RTVEC_ELT (v, 2), 0)) + && REGNO (XEXP (RTVEC_ELT (v, 2), 0)) == TOC_REGNUM + && GET_CODE (XEXP (RTVEC_ELT (v, 2), 1)) == UNSPEC + && XINT (XEXP (RTVEC_ELT (v, 2), 1), 1) == UNSPEC_TOCSLOT + && XVECLEN (XEXP (RTVEC_ELT (v, 2), 1), 0) == 1 + && CONST_INT_P (XVECEXP (XEXP (RTVEC_ELT (v, 2), 1), 0, 0)) + && GET_CODE (RTVEC_ELT (v, 3)) == CLOBBER + && REG_P (XEXP (RTVEC_ELT (v, 3), 0)) + && REGNO (XEXP (RTVEC_ELT (v, 3), 0)) == LR_REGNO); + else if (DEFAULT_ABI == ABI_AIX) + return (n == 5 && GET_CODE (RTVEC_ELT (v, 2)) == USE + && GET_CODE (XEXP (RTVEC_ELT (v, 2), 0)) == MEM + && GET_CODE (RTVEC_ELT (v, 3)) == SET + && REG_P (XEXP (RTVEC_ELT (v, 3), 0)) + && REGNO (XEXP (RTVEC_ELT (v, 3), 0)) == TOC_REGNUM + && GET_CODE (XEXP (RTVEC_ELT (v, 3), 1)) == UNSPEC + && XINT (XEXP (RTVEC_ELT (v, 3), 1), 1) == UNSPEC_TOCSLOT + && XVECLEN (XEXP (RTVEC_ELT (v, 3), 1), 0) == 1 + && CONST_INT_P (XVECEXP (XEXP (RTVEC_ELT (v, 3), 1), 0, 0)) + && GET_CODE (RTVEC_ELT (v, 4)) == CLOBBER + && REG_P (XEXP (RTVEC_ELT (v, 4), 0)) + && REGNO (XEXP (RTVEC_ELT (v, 4), 0)) == LR_REGNO); + else if (DEFAULT_ABI == ABI_V4) + return (n == 4 && GET_CODE (RTVEC_ELT (v, 2)) == USE + && CONST_INT_P (XEXP (RTVEC_ELT (v, 2), 0)) + && GET_CODE (RTVEC_ELT (v, 3)) == CLOBBER + && REG_P (XEXP (RTVEC_ELT (v, 3), 0)) + && REGNO (XEXP (RTVEC_ELT (v, 3), 0)) == LR_REGNO); + else + gcc_unreachable (); + } + else + return 0; +}) + ;; Return 1 if the operand is a SYMBOL_REF for a function known to be in ;; this file. (define_predicate "current_file_function_operand" diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index a25755418ea..4e3c5fc135f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -37918,9 +37918,10 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) { rtx func = func_desc; rtx func_addr; - rtx call[3]; + rtx call[4]; rtx insn; rtx abi_reg = NULL_RTX; + int n; if (global_tlsarg) tlsarg = global_tlsarg; @@ -37968,9 +37969,16 @@ rs6000_call_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) call[0] = gen_rtx_SET (value, call[0]); call[1] = gen_rtx_USE (VOIDmode, cookie); - call[2] = gen_hard_reg_clobber (Pmode, LR_REGNO); + n = 2; + if (TARGET_SECURE_PLT + && flag_pic + && GET_CODE (func_addr) == SYMBOL_REF + && !SYMBOL_REF_LOCAL_P (func_addr)) + call[n++] = gen_rtx_USE (VOIDmode, pic_offset_table_rtx); - insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call)); + call[n++] = gen_hard_reg_clobber (Pmode, LR_REGNO); + + insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (n, call)); insn = emit_call_insn (insn); if (abi_reg) use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 56364e0e43b..0d5ef31f9f2 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -9443,7 +9443,7 @@ (define_peephole2 ;; TLS support. (define_insn "*tls_gdld_nomark" - [(match_parallel 3 "" + [(match_parallel 3 "tls_nomark_call" [(set (match_operand:P 0 "gpc_reg_operand" "=b") (call (mem:SI (match_operand:P 1)) (match_operand:P 2 "unspec_tls"))) @@ -9470,15 +9470,43 @@ (define_insn "*tls_gdld_nomark" else output_asm_insn ("addi %0,%1,%&@got@tlsld", op); } - return rs6000_call_template (operands, 1); + if (GET_CODE (operands[1]) == SYMBOL_REF) + return rs6000_call_template (operands, 1); + + /* Indirect calls need to recog a few more operands. See the various + call_value_indirect patterns, and note that edit_tls_call_insn + added an extra element to the parallel. */ + rtx par = operands[3]; + rtvec v = XVEC (par, 0); + if (DEFAULT_ABI == ABI_ELFv2) + operands[3] = XVECEXP (XEXP (RTVEC_ELT (v, 2), 1), 0, 0); + else if (DEFAULT_ABI == ABI_AIX) + { + operands[3] = XEXP (RTVEC_ELT (v, 2), 0); + operands[4] = XVECEXP (XEXP (RTVEC_ELT (v, 3), 1), 0, 0); + } + else if (DEFAULT_ABI == ABI_V4) + operands[3] = XEXP (RTVEC_ELT (v, 2), 0); + else + gcc_unreachable (); + return rs6000_indirect_call_template (operands, 1); } [(set_attr "type" "two") (set (attr "length") - (cond [(match_test "TARGET_CMODEL != CMODEL_SMALL") - (const_int 16) - (match_test "DEFAULT_ABI != ABI_V4") - (const_int 12)] - (const_int 8)))]) + (plus (if_then_else (match_test "TARGET_CMODEL != CMODEL_SMALL") + (const_int 8) + (const_int 4)) + (plus (if_then_else (match_test "GET_CODE (operands[1]) != SYMBOL_REF") + (plus (if_then_else (match_test "!rs6000_speculate_indirect_jumps") + (const_int 4) + (const_int 0)) + (if_then_else (match_test "DEFAULT_ABI == ABI_AIX") + (const_int 4) + (const_int 0))) + (const_int 0)) + (if_then_else (match_test "DEFAULT_ABI != ABI_V4") + (const_int 8) + (const_int 4)))))]) (define_insn_and_split "*tls_gd" [(set (match_operand:P 0 "gpc_reg_operand" "=b") @@ -10440,7 +10468,7 @@ (define_insn "*call_indirect_nonlocal_sysv" (const_string "8")] (const_string "4")))]) -(define_insn_and_split "*call_nonlocal_sysv" +(define_insn "*call_nonlocal_sysv" [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s")) (match_operand 1)) (use (match_operand:SI 2 "immediate_operand" "O,n")) @@ -10456,17 +10484,6 @@ (define_insn_and_split "*call_nonlocal_sysv" output_asm_insn ("creqv 6,6,6", operands); return rs6000_call_template (operands, 0); -} - "DEFAULT_ABI == ABI_V4 - && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[0]) - && (INTVAL (operands[2]) & CALL_LONG) == 0" - [(parallel [(call (mem:SI (match_dup 0)) - (match_dup 1)) - (use (match_dup 2)) - (use (match_dup 3)) - (clobber (reg:SI LR_REGNO))])] -{ - operands[3] = pic_offset_table_rtx; } [(set_attr "type" "branch,branch") (set_attr "length" "4,8")]) @@ -10521,7 +10538,7 @@ (define_insn "*call_value_indirect_nonlocal_sysv" (const_string "8")] (const_string "4")))]) -(define_insn_and_split "*call_value_nonlocal_sysv" +(define_insn "*call_value_nonlocal_sysv" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s")) (match_operand 2))) @@ -10538,18 +10555,6 @@ (define_insn_and_split "*call_value_nonlocal_sysv" output_asm_insn ("creqv 6,6,6", operands); return rs6000_call_template (operands, 1); -} - "DEFAULT_ABI == ABI_V4 - && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[1]) - && (INTVAL (operands[3]) & CALL_LONG) == 0" - [(parallel [(set (match_dup 0) - (call (mem:SI (match_dup 1)) - (match_dup 2))) - (use (match_dup 3)) - (use (match_dup 4)) - (clobber (reg:SI LR_REGNO))])] -{ - operands[4] = pic_offset_table_rtx; } [(set_attr "type" "branch,branch") (set_attr "length" "4,8")])