From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from azure-sdnproxy.icoremail.net (azure-sdnproxy.icoremail.net [207.46.229.174]) by sourceware.org (Postfix) with ESMTP id 98DF8385829F for ; Tue, 28 Nov 2023 02:33:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 98DF8385829F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=eswincomputing.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 98DF8385829F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=207.46.229.174 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701138804; cv=none; b=LvmtTf7JProB8BHF9sRpOhMoTjD167WT99wzZrRg999ZXJ4Fneq6LPGVbboOsj5ROdABb1PEmonohz0QYd1RfYeHBcAMUGw0XrmyONNn8TmdZ7dU/4UM6ii2Nt+KUApMe9F9yaTMQV8IX/a1RVW3+SE1QeHob35zR6mZqc6vMUI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701138804; c=relaxed/simple; bh=DFyqv+TlXWpxDi7qLK0jTNoQ2p/OuWaOXkSf/KkXB2Q=; h=From:To:Subject:Date:Message-Id; b=moox1btp95UubYB2E25xmmY6N3bov28Gv15pUzqYUq6yeUwEXuTmrAKfoaK7P2OeevvqKbQ4HVfUjs75TYlIIZKLdoryJTFMm9XSM2gaOWQuuBKgCnnjC1TcyMspbtrap6Np6Dx6yb0jXcqr9fSofpcsAua/JmQ7bBc3Tmh1Aug= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from localhost.localdomain (unknown [10.12.130.31]) by app1 (Coremail) with SMTP id TAJkCgA3H4E0UWVl1pkBAA--.18663S5; Tue, 28 Nov 2023 10:32:23 +0800 (CST) From: Fei Gao To: gcc-patches@gcc.gnu.org Cc: kito.cheng@gmail.com, palmer@dabbelt.com, jeffreyalaw@gmail.com, zengxiao@eswincomputing.com, Fei Gao Subject: [PATCH 2/4] [ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns Date: Tue, 28 Nov 2023 02:32:25 +0000 Message-Id: <20231128023227.36200-2-gaofei@eswincomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20231128023227.36200-1-gaofei@eswincomputing.com> References: <20231128023227.36200-1-gaofei@eswincomputing.com> X-CM-TRANSID:TAJkCgA3H4E0UWVl1pkBAA--.18663S5 X-Coremail-Antispam: 1UD129KBjvAXoWfJw1DCFWkGF1rKw1xAFy8uFg_yoW8WF15Ao WfZrZ8tF40gr13WF1xGr4Y9r1jqa1UZr98Cr4Yvr1Y9rWqyrySgw4rWa1DZa48Wr4S9ry7 Aanaqr1Iy3y5Arnxn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYC7AC8VAFwI0_Gr0_Xr1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r18M28IrcIa0x kI8VCY1x0267AKxVWUCVW8JwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26w1j6s0DM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr 1l84ACjcxK6I8E87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0D M2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjx v20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1l F7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20x vY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I 3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIx AIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAI cVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4A2js IEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUyKZAUUUUU= X-CM-SenderInfo: xjdrwv3l6h245lqf0zpsxwx03jof0z/ X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_STATUS,KAM_SHORT,LIKELY_SPAM_BODY,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: op=[PLUS, MINUS, IOR, XOR, ASHIFT, ASHIFTRT, LSHIFTRT, ROTATE, ROTATERT] SIGN_EXTEND, ZERO_EXTEND and SUBREG has been considered to support SImode in 64-bit machine. Conditional op, if zero rd = (rc == 0) ? (rs1 op rs2) : rs1 --> czero.nez rd, rs2, rc op rd, rs1, rd Conditional op, if non-zero rd = (rc != 0) ? (rs1 op rs2) : rs1 --> czero.eqz rd, rs2, rc op rd, rs1, rd Co-authored-by: Xiao Zeng gcc/ChangeLog: * ifcvt.cc (noce_try_cond_zero_arith):handler for condtional zero based ifcvt (noce_emit_czero): helper for noce_try_cond_zero_arith (noce_cond_zero_binary_op_supported): check supported OPs for condtional zero based ifcvt (get_base_reg): get base reg of a subreg or the reg itself (noce_bbs_ok_for_cond_zero_arith): check if BBs are OK for condtional zero based ifcvt (noce_process_if_block): add noce_try_cond_zero_arith gcc/testsuite/ChangeLog: * gcc.target/riscv/zicond_ifcvt_opt.c: New test. --- gcc/ifcvt.cc | 210 ++++++ .../gcc.target/riscv/zicond_ifcvt_opt.c | 682 ++++++++++++++++++ 2 files changed, 892 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc index a0af553b9ff..8f6a0e7f5fe 100644 --- a/gcc/ifcvt.cc +++ b/gcc/ifcvt.cc @@ -787,6 +787,7 @@ static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx_insn **); static bool noce_try_minmax (struct noce_if_info *); static bool noce_try_abs (struct noce_if_info *); static bool noce_try_sign_mask (struct noce_if_info *); +static int noce_try_cond_zero_arith (struct noce_if_info *); /* Return the comparison code for reversed condition for IF_INFO, or UNKNOWN if reversing the condition is not possible. */ @@ -1831,6 +1832,40 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, return NULL_RTX; } +/* Emit a conditional zero, returning TARGET or NULL_RTX upon failure. + IF_INFO describes the if-conversion scenario under consideration. + CZERO_CODE selects the condition (EQ/NE). + NON_ZERO_OP is the nonzero operand of the conditional move + TARGET is the desired output register. */ + +static rtx +noce_emit_czero (struct noce_if_info *if_info, enum rtx_code czero_code, + rtx non_zero_op, rtx target) +{ + machine_mode mode = GET_MODE (target); + rtx cond_op0 = XEXP (if_info->cond, 0); + rtx czero_cond + = gen_rtx_fmt_ee (czero_code, GET_MODE (cond_op0), cond_op0, const0_rtx); + rtx if_then_else + = gen_rtx_IF_THEN_ELSE (mode, czero_cond, const0_rtx, non_zero_op); + rtx set = gen_rtx_SET (target, if_then_else); + + start_sequence (); + rtx_insn *insn = emit_insn (set); + + if (recog_memoized (insn) >= 0) + { + rtx_insn *seq = get_insns (); + end_sequence (); + emit_insn (seq); + + return target; + } + + end_sequence (); + return NULL_RTX; +} + /* Try only simple constants and registers here. More complex cases are handled in noce_try_cmove_arith after noce_try_store_flag_arith has had a go at it. */ @@ -2880,6 +2915,178 @@ noce_try_sign_mask (struct noce_if_info *if_info) return true; } +/* Check if OP is supported by conditional zero based if conversion, + returning TRUE if satisfied otherwise FALSE. + + OP is the operation to check. */ + +static bool +noce_cond_zero_binary_op_supported (rtx op) +{ + enum rtx_code opcode = GET_CODE (op); + + /* Strip SIGN_EXTEND or ZERO_EXTEND if any. */ + if (opcode == SIGN_EXTEND || opcode == ZERO_EXTEND) + opcode = GET_CODE (XEXP (op, 0)); + + if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR + || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT + || opcode == ROTATE || opcode == ROTATERT) + return true; + + return false; +} + +/* Helper function to return REG itself or inner expression of a SUBREG, + otherwise NULL_RTX for other RTX_CODE. */ + +static rtx +get_base_reg (rtx exp) +{ + if (REG_P (exp)) + return exp; + else if (SUBREG_P (exp)) + return SUBREG_REG (exp); + + return NULL_RTX; +} + +/* Check if IF-BB and THEN-BB satisfy the condition for conditional zero + based if conversion, returning TRUE if satisfied otherwise FALSE. + + IF_INFO describes the if-conversion scenario under consideration. + COMMON_PTR points to the common REG of canonicalized IF_INFO->A and + IF_INFO->B. + CZERO_CODE_PTR points to the comparison code to use in czero RTX. + A_PTR points to the A expression of canonicalized IF_INFO->A. + TO_REPLACE points to the RTX to be replaced by czero RTX destnation. */ + +static bool +noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr, + enum rtx_code *czero_code_ptr, rtx *a_ptr, + rtx **to_replace) +{ + rtx common = NULL_RTX; + rtx cond = if_info->cond; + rtx a = copy_rtx (if_info->a); + rtx b = copy_rtx (if_info->b); + rtx bin_op1 = NULL_RTX; + enum rtx_code czero_code = UNKNOWN; + bool reverse = false; + rtx op0, op1, bin_exp; + + if (!noce_simple_bbs (if_info)) + return false; + + /* COND must be EQ or NE comparision of a reg and 0. */ + if (GET_CODE (cond) != NE && GET_CODE (cond) != EQ) + return false; + if (!REG_P (XEXP (cond, 0)) || !rtx_equal_p (XEXP (cond, 1), const0_rtx)) + return false; + + /* Canonicalize x = y : (y op z) to x = (y op z) : y. */ + if (REG_P (a) && noce_cond_zero_binary_op_supported (b)) + { + std::swap (a, b); + reverse = !reverse; + } + + /* Check if x = (y op z) : y is supported by czero based ifcvt. */ + if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b))) + return false; + + /* Strip sign_extend if any. */ + if (GET_CODE (a) == SIGN_EXTEND || GET_CODE (a) == ZERO_EXTEND) + bin_exp = XEXP (a, 0); + else + bin_exp = a; + + /* Canonicalize x = (z op y) : y to x = (y op z) : y */ + op1 = get_base_reg (XEXP (bin_exp, 1)); + if (op1 && rtx_equal_p (op1, b) && COMMUTATIVE_ARITH_P (bin_exp)) + std::swap (XEXP (bin_exp, 0), XEXP (bin_exp, 1)); + + op0 = get_base_reg (XEXP (bin_exp, 0)); + if (op0 && rtx_equal_p (op0, b)) + { + common = b; + bin_op1 = XEXP (bin_exp, 1); + czero_code = reverse + ? noce_reversed_cond_code (if_info) + : GET_CODE (cond); + } + else + return false; + + if (czero_code == UNKNOWN) + return false; + + if (CONST_INT_P (bin_op1) || REG_P (bin_op1)) + *to_replace = &XEXP (bin_exp, 1); + else if (SUBREG_P (bin_op1)) + *to_replace = &SUBREG_REG (XEXP (bin_exp, 1)); + else + return false; + + *common_ptr = common; + *czero_code_ptr = czero_code; + *a_ptr = a; + + return true; +} + +/* Try to covert if-then-else with conditional zero, + returning TURE on success or FALSE on failure. + IF_INFO describes the if-conversion scenario under consideration. */ + +static int +noce_try_cond_zero_arith (struct noce_if_info *if_info) +{ + rtx target, a; + rtx_insn *seq; + machine_mode mode = GET_MODE (if_info->x); + rtx common = NULL_RTX; + enum rtx_code czero_code = UNKNOWN; + rtx non_zero_op = NULL_RTX; + rtx *to_replace = NULL; + + if (!noce_bbs_ok_for_cond_zero_arith (if_info, &common, &czero_code, &a, + &to_replace)) + return false; + + /* Disallow CONST_INT currently for simplicity*/ + if (to_replace == NULL || !REG_P (*to_replace)) + return false; + + non_zero_op = *to_replace; + + start_sequence (); + + /* If x is used in both input and out like x = c ? x + z : x, + use a new reg to avoid modifying x */ + if (common && rtx_equal_p (common, if_info->x)) + target = gen_reg_rtx (mode); + else + target = if_info->x; + + target = noce_emit_czero (if_info, czero_code, non_zero_op, target); + if (!target || !to_replace) + { + end_sequence (); + return false; + } + + *to_replace = target; + emit_insn (gen_rtx_SET (if_info->x, a)); + + seq = end_ifcvt_sequence (if_info); + if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info)) + return false; + + emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a)); + if_info->transform_name = "noce_try_cond_zero_arith"; + return true; +} /* Optimize away "if (x & C) x |= C" and similar bit manipulation transformations. */ @@ -3975,6 +4182,9 @@ noce_process_if_block (struct noce_if_info *if_info) goto success; if (noce_try_store_flag_mask (if_info)) goto success; + if (HAVE_conditional_move + && noce_try_cond_zero_arith (if_info)) + goto success; if (HAVE_conditional_move && noce_try_cmove_arith (if_info)) goto success; diff --git a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c new file mode 100644 index 00000000000..9357f26d978 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c @@ -0,0 +1,682 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zbb_zicond -mabi=lp64d -O2 " } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os" "-Og" "-O3" "-Oz" "-flto"} } */ + +long +test_ADD_ceqz (long x, long y, long z, long c) +{ + if (c) + x = y + z; + else + x = y; + return x; +} + +long +test_ADD_ceqz_x (long x, long z, long c) +{ + if (c) + x = x + z; + + return x; +} + +long +test_ADD_nez (long x, long y, long z, long c) +{ + if (c) + x = y; + else + x = y + z; + return x; +} + +long +test_ADD_nez_x (long x, long z, long c) +{ + if (c) + { + } + else + x = x + z; + return x; +} + +long +test_ADD_nez_2 (long x, long y, long z, long c) +{ + if (!c) + x = y + z; + else + x = y; + return x; +} + +long +test_ADD_nez_x_2 (long x, long z, long c) +{ + if (!c) + x = x + z; + + return x; +} + +long +test_ADD_eqz_2 (long x, long y, long z, long c) +{ + if (!c) + x = y; + else + x = y + z; + return x; +} + +long +test_ADD_eqz_x_2 (long x, long z, long c) +{ + if (!c) + { + } + else + x = x + z; + return x; +} + +long +test_SUB_ceqz (long x, long y, long z, long c) +{ + if (c) + x = y - z; + else + x = y; + return x; +} + +long +test_SUB_ceqz_x (long x, long z, long c) +{ + if (c) + x = x - z; + + return x; +} + +long +test_SUB_nez (long x, long y, long z, long c) +{ + if (c) + x = y; + else + x = y - z; + return x; +} + +long +test_SUB_nez_x (long x, long z, long c) +{ + if (c) + { + } + else + x = x - z; + return x; +} + +long +test_SUB_nez_2 (long x, long y, long z, long c) +{ + if (!c) + x = y - z; + else + x = y; + return x; +} + +long +test_SUB_nez_x_2 (long x, long z, long c) +{ + if (!c) + x = x - z; + + return x; +} + +long +test_SUB_eqz_2 (long x, long y, long z, long c) +{ + if (!c) + x = y; + else + x = y - z; + return x; +} + +long +test_SUB_eqz_x_2 (long x, long z, long c) +{ + if (!c) + { + } + else + x = x - z; + return x; +} + +long +test_IOR_ceqz (long x, long y, long z, long c) +{ + if (c) + x = y | z; + else + x = y; + return x; +} + +long +test_IOR_ceqz_x (long x, long z, long c) +{ + if (c) + x = x | z; + + return x; +} + +long +test_IOR_nez (long x, long y, long z, long c) +{ + if (c) + x = y; + else + x = y | z; + return x; +} + +long +test_IOR_nez_x (long x, long z, long c) +{ + if (c) + { + } + else + x = x | z; + return x; +} + +long +test_IOR_nez_2 (long x, long y, long z, long c) +{ + if (!c) + x = y | z; + else + x = y; + return x; +} + +long +test_IOR_nez_x_2 (long x, long z, long c) +{ + if (!c) + x = x | z; + + return x; +} + +long +test_IOR_eqz_2 (long x, long y, long z, long c) +{ + if (!c) + x = y; + else + x = y | z; + return x; +} + +long +test_IOR_eqz_x_2 (long x, long z, long c) +{ + if (!c) + { + } + else + x = x | z; + return x; +} + +long +test_XOR_ceqz (long x, long y, long z, long c) +{ + if (c) + x = y ^ z; + else + x = y; + return x; +} + +long +test_XOR_ceqz_x (long x, long z, long c) +{ + if (c) + x = x ^ z; + + return x; +} + +long +test_XOR_nez (long x, long y, long z, long c) +{ + if (c) + x = y; + else + x = y ^ z; + return x; +} + +long +test_XOR_nez_x (long x, long z, long c) +{ + if (c) + { + } + else + x = x ^ z; + return x; +} + +long +test_XOR_nez_2 (long x, long y, long z, long c) +{ + if (!c) + x = y ^ z; + else + x = y; + return x; +} + +long +test_XOR_nez_x_2 (long x, long z, long c) +{ + if (!c) + x = x ^ z; + + return x; +} + +long +test_XOR_eqz_2 (long x, long y, long z, long c) +{ + if (!c) + x = y; + else + x = y ^ z; + return x; +} + +long +test_XOR_eqz_x_2 (long x, long z, long c) +{ + if (!c) + { + } + else + x = x ^ z; + return x; +} + +long +test_ADD_ceqz_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (c) + x = z + y; + else + x = y; + return x; +} + +long +test_ADD_ceqz_x_reverse_bin_oprands (long x, long z, long c) +{ + if (c) + x = z + x; + + return x; +} + +long +test_ADD_nez_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (c) + x = y; + else + x = z + y; + return x; +} + +long +test_ADD_nez_x_reverse_bin_oprands (long x, long z, long c) +{ + if (c) + { + } + else + x = z + x; + return x; +} + +long +test_ADD_nez_2_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (!c) + x = z + y; + else + x = y; + return x; +} + +long +test_ADD_nez_x_2_reverse_bin_oprands (long x, long z, long c) +{ + if (!c) + x = z + x; + + return x; +} + +long +test_ADD_eqz_2_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (!c) + x = y; + else + x = z + y; + return x; +} + +long +test_ADD_eqz_x_2_reverse_bin_oprands (long x, long z, long c) +{ + if (!c) + { + } + else + x = z + x; + return x; +} + +long +test_IOR_ceqz_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (c) + x = z | y; + else + x = y; + return x; +} + +long +test_IOR_ceqz_x_reverse_bin_oprands (long x, long z, long c) +{ + if (c) + x = z | x; + + return x; +} + +long +test_IOR_nez_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (c) + x = y; + else + x = z | y; + return x; +} + +long +test_IOR_nez_x_reverse_bin_oprands (long x, long z, long c) +{ + if (c) + { + } + else + x = z | x; + return x; +} + +long +test_IOR_nez_2_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (!c) + x = z | y; + else + x = y; + return x; +} + +long +test_IOR_nez_x_2_reverse_bin_oprands (long x, long z, long c) +{ + if (!c) + x = z | x; + + return x; +} + +long +test_IOR_eqz_2_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (!c) + x = y; + else + x = z | y; + return x; +} + +long +test_IOR_eqz_x_2_reverse_bin_oprands (long x, long z, long c) +{ + if (!c) + { + } + else + x = z | x; + return x; +} + +long +test_XOR_ceqz_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (c) + x = z ^ y; + else + x = y; + return x; +} + +long +test_XOR_ceqz_x_reverse_bin_oprands (long x, long z, long c) +{ + if (c) + x = z ^ x; + + return x; +} + +long +test_XOR_nez_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (c) + x = y; + else + x = z ^ y; + return x; +} + +long +test_XOR_nez_x_reverse_bin_oprands (long x, long z, long c) +{ + if (c) + { + } + else + x = z ^ x; + return x; +} + +long +test_XOR_nez_2_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (!c) + x = z ^ y; + else + x = y; + return x; +} + +long +test_XOR_nez_x_2_reverse_bin_oprands (long x, long z, long c) +{ + if (!c) + x = z ^ x; + + return x; +} + +long +test_XOR_eqz_2_reverse_bin_oprands (long x, long y, long z, long c) +{ + if (!c) + x = y; + else + x = z ^ y; + return x; +} + +long +test_XOR_eqz_x_2_reverse_bin_oprands (long x, long z, long c) +{ + if (!c) + { + } + else + x = z ^ x; + return x; +} + +long +test_ShiftLeft_eqz (long x, long y, long z, long c) +{ + if (c) + x = y << z; + else + x = y; + return x; +} + +long +test_ShiftR_eqz (long x, long y, long z, long c) +{ + if (c) + x = y >> z; + else + x = y; + return x; +} + +unsigned long +test_ShiftR_logical_eqz (unsigned long x, unsigned long y, unsigned long z, + unsigned long c) +{ + if (c) + x = y >> z; + else + x = y; + return x; +} + +unsigned long +test_RotateL_eqz (unsigned long x, unsigned long y, unsigned long z, + unsigned long c) +{ + if (c) + x = (y << z) | (y >> (64 - z)); + else + x = y; + return x; +} + +unsigned long +test_RotateR_eqz (unsigned long x, unsigned long y, unsigned long z, + unsigned long c) +{ + if (c) + x = (y >> z) | (y << (64 - z)); + else + x = y; + return x; +} + +int +test_ADD_ceqz_int (int x, int y, int z, int c) +{ + if (c) + x = y + z; + else + x = y; + return x; +} + +int +test_ShiftLeft_eqz_int (int x, int y, int z, int c) +{ + if (c) + x = y << z; + else + x = y; + return x; +} + +int +test_ShiftR_eqz_int (int x, int y, int z, int c) +{ + if (c) + x = y >> z; + else + x = y; + return x; +} + +unsigned int +test_ShiftR_logical_eqz_int (unsigned int x, unsigned int y, unsigned int z, + unsigned int c) +{ + if (c) + x = y >> z; + else + x = y; + return x; +} + +unsigned int +test_RotateL_eqz_int (unsigned int x, unsigned int y, unsigned int z, + unsigned int c) +{ + if (c) + x = (y << z) | (y >> (32 - z)); + else + x = y; + return x; +} + +unsigned int +test_RotateR_eqz_int (unsigned int x, unsigned int y, unsigned int z, + unsigned int c) +{ + if (c) + x = (y >> z) | (y << (32 - z)); + else + x = y; + return x; +} + +/* { dg-final { scan-assembler-times {czero\.eqz} 39 } } */ +/* { dg-final { scan-assembler-times {czero\.nez} 28 } } */ -- 2.17.1