From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by sourceware.org (Postfix) with ESMTPS id 2D3A9385B83F for ; Fri, 25 Jun 2021 16:09:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2D3A9385B83F Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 15PG3sPV053529; Fri, 25 Jun 2021 12:09:25 -0400 Received: from ppma04ams.nl.ibm.com (63.31.33a9.ip4.static.sl-reverse.com [169.51.49.99]) by mx0b-001b2d01.pphosted.com with ESMTP id 39dh5yk831-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 25 Jun 2021 12:09:25 -0400 Received: from pps.filterd (ppma04ams.nl.ibm.com [127.0.0.1]) by ppma04ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 15PG89Pf017331; Fri, 25 Jun 2021 16:09:23 GMT Received: from b06cxnps4075.portsmouth.uk.ibm.com (d06relay12.portsmouth.uk.ibm.com [9.149.109.197]) by ppma04ams.nl.ibm.com with ESMTP id 399878b4q0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 25 Jun 2021 16:09:23 +0000 Received: from d06av26.portsmouth.uk.ibm.com (d06av26.portsmouth.uk.ibm.com [9.149.105.62]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 15PG9Khk28443098 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 25 Jun 2021 16:09:21 GMT Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C68FCAE071; Fri, 25 Jun 2021 16:09:20 +0000 (GMT) Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7AF9CAE065; Fri, 25 Jun 2021 16:09:20 +0000 (GMT) Received: from li-926bd7cc-2dd1-11b2-a85c-f6adc0f5efec.ibm.com (unknown [9.171.46.33]) by d06av26.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 25 Jun 2021 16:09:20 +0000 (GMT) From: Robin Dapp To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [PATCH 1/7] ifcvt: Check if cmovs are needed. Date: Fri, 25 Jun 2021 18:08:59 +0200 Message-Id: <20210625160905.23786-2-rdapp@linux.ibm.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210625160905.23786-1-rdapp@linux.ibm.com> References: <20210625160905.23786-1-rdapp@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: USdA79WDRtCSBiHktvK9hZe4yYF-29d2 X-Proofpoint-GUID: USdA79WDRtCSBiHktvK9hZe4yYF-29d2 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.790 definitions=2021-06-25_05:2021-06-25, 2021-06-25 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 phishscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 adultscore=0 spamscore=0 mlxscore=0 priorityscore=1501 suspectscore=0 bulkscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106250094 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Jun 2021 16:09:31 -0000 When if-converting multiple SETs and we encounter a swap-style idiom if (a > b) { tmp = c; // [1] c = d; d = tmp; } ifcvt should not generate a conditional move for the instruction at [1]. In order to achieve that, this patch goes through all relevant SETs and marks the relevant instructions. This helps to evaluate costs. On top, only generate temporaries if the current cmov is going to overwrite one of the comparands of the initial compare. --- gcc/ifcvt.c | 104 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 017944f4f79..eef6490626a 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -98,6 +98,7 @@ static int dead_or_predicable (basic_block, basic_block, basic_block, edge, int); static void noce_emit_move_insn (rtx, rtx); static rtx_insn *block_has_only_trap (basic_block); +static void check_need_cmovs (basic_block, hash_map *); /* Count the number of non-jump active insns in BB. */ @@ -3203,6 +3204,10 @@ noce_convert_multiple_sets (struct noce_if_info *if_info) auto_vec unmodified_insns; int count = 0; + hash_map need_cmovs; + + check_need_cmovs (then_bb, &need_cmovs); + FOR_BB_INSNS (then_bb, insn) { /* Skip over non-insns. */ @@ -3213,26 +3218,38 @@ noce_convert_multiple_sets (struct noce_if_info *if_info) gcc_checking_assert (set); rtx target = SET_DEST (set); - rtx temp = gen_reg_rtx (GET_MODE (target)); + rtx temp; rtx new_val = SET_SRC (set); rtx old_val = target; - /* If we were supposed to read from an earlier write in this block, - we've changed the register allocation. Rewire the read. While - we are looking, also try to catch a swap idiom. */ - for (int i = count - 1; i >= 0; --i) - if (reg_overlap_mentioned_p (new_val, targets[i])) - { - /* Catch a "swap" style idiom. */ - if (find_reg_note (insn, REG_DEAD, new_val) != NULL_RTX) - /* The write to targets[i] is only live until the read - here. As the condition codes match, we can propagate - the set to here. */ - new_val = SET_SRC (single_set (unmodified_insns[i])); - else - new_val = temporaries[i]; - break; - } + /* As we are transforming + if (x > y) + a = b; + c = d; + into + a = (x > y) ... + c = (x > y) ... + + we potentially check x > y before every set here. + (Even though might be removed by subsequent passes.) + We cannot transform + if (x > y) + x = y; + ... + into + x = (x > y) ... + ... + since this would invalidate x. Therefore we introduce a temporary + every time we are about to overwrite a variable used in the + check. Costing of a sequence with these is going to be inaccurate. */ + if (reg_overlap_mentioned_p (target, cond)) + temp = gen_reg_rtx (GET_MODE (target)); + else + temp = target; + + bool need_cmov = true; + if (need_cmovs.get (insn)) + need_cmov = false; /* If we had a non-canonical conditional jump (i.e. one where the fallthrough is to the "else" case) we need to reverse @@ -3808,6 +3825,59 @@ check_cond_move_block (basic_block bb, return TRUE; } +/* Find local swap-style idioms in BB and mark the first insn (1) + that is only a temporary as not needing a conditional move as + it is going to be dead afterwards anyway. + + (1) int tmp = a; + a = b; + b = tmp; + + ifcvt + --> + + load tmp,a + cmov a,b + cmov b,tmp */ + +static void +check_need_cmovs (basic_block bb, hash_map *need_cmov) +{ + rtx_insn *insn; + int count = 0; + auto_vec insns; + auto_vec dests; + + FOR_BB_INSNS (bb, insn) + { + rtx set, src, dest; + + if (!active_insn_p (insn)) + continue; + + set = single_set (insn); + if (set == NULL_RTX) + continue; + + src = SET_SRC (set); + dest = SET_DEST (set); + + for (int i = count - 1; i >= 0; --i) + { + if (reg_overlap_mentioned_p (src, dests[i]) + && find_reg_note (insn, REG_DEAD, src) != NULL_RTX) + { + need_cmov->put (insns[i], false); + } + } + + insns.safe_push (insn); + dests.safe_push (dest); + + count++; + } +} + /* Given a basic block BB suitable for conditional move conversion, a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing the register values depending on COND, emit the insns in the block as -- 2.31.1