From a5f9fb98c890c144541c5ed95390844af69e9130 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 3 Nov 2025 01:12:57 +0000 Subject: [PATCH 1/3] LoongArch: Implement NOCE_CONVERSION_PROFITABLE_P to be compatible Signed-off-by: Peng Fan --- gcc/config/loongarch/loongarch.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index c90fc726f05..283dbaba06a 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -11177,6 +11177,23 @@ loongarch_c_mode_for_suffix (char suffix) return VOIDmode; } +static bool +loongarch_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info) +{ + rtx src, dst; + enum rtx_code code; + for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn)) + { + src = SET_SRC (single_set (insn)); + dst = SET_DEST (single_set (insn)); + code = GET_CODE (src); + if (REG_P (dst) && (code == LTU || code == LEU || code == GEU || code == GTU)) + return false; + } + + return default_noce_conversion_profitable_p (seq, if_info); +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -11448,6 +11465,9 @@ loongarch_c_mode_for_suffix (char suffix) #undef TARGET_C_MODE_FOR_SUFFIX #define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix +#undef TARGET_NOCE_CONVERSION_PROFITABLE_P +#define TARGET_NOCE_CONVERSION_PROFITABLE_P loongarch_noce_conversion_profitable_p + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-loongarch.h" -- Gitee From b68f4a950fb0903a2d0e9f2a0644a8241600d4eb Mon Sep 17 00:00:00 2001 From: Jinyang He Date: Wed, 29 Oct 2025 16:07:35 +0800 Subject: [PATCH 2/3] LoongArch: Only allow valid binary op when optimize conditional move It is wrong that optimize from `if (cond) dest op= 1 << shift` to `dest op= (cond ? 1 : 0) << shift` when `dest op 0 != dest`. Like `and`, `mul` or `div`. And in this optimization `mul` and `div` is optimized to shift. gcc/ChangeLog: * config/loongarch/loongarch.cc (loongarch_expand_conditional_move): Only allow valid binary op when optimize conditional move. gcc/testsuite/ChangeLog: * gcc.target/loongarch/conditional-move-opt-1.c: Remove mul. * gcc.target/loongarch/conditional-move-opt-2.c: Remove and. * gcc.target/loongarch/conditional-move-opt-3.c: New test. Co-Authored-By: Peng Fan --- gcc/config/loongarch/loongarch.cc | 26 ++++++++++++++++--- .../loongarch/conditional-move-opt-1.c | 4 +-- .../loongarch/conditional-move-opt-2.c | 2 +- .../loongarch/conditional-move-opt-3.c | 14 ++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 283dbaba06a..15230b91733 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -5426,12 +5426,32 @@ loongarch_expand_conditional_move (rtx *operands) } } + auto is_binary_op_0_keep_orig = [](enum rtx_code code) + { + switch (code) + { + case PLUS: + case MINUS: + case IOR: + case XOR: + case ROTATE: + case ROTATERT: + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + return true; + default: + return false; + } + }; + /* Check if the optimization conditions are met. */ if (value_if_true_insn && value_if_false_insn - /* Make sure that value_if_false and var are the same. */ - && BINARY_P (value_if_true_insn_src - = SET_SRC (single_set (value_if_true_insn))) + /* Make sure that the orig value OP 0 keep orig. */ + && (value_if_true_insn_src + = SET_SRC (single_set (value_if_true_insn))) + && is_binary_op_0_keep_orig ( GET_CODE (value_if_true_insn_src)) /* Make sure that both value_if_true and value_if_false has the same var. */ && rtx_equal_p (XEXP (value_if_true_insn_src, 0), diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c index ed13471aa90..47802aa9688 100644 --- a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c @@ -27,7 +27,7 @@ void test_lt () { if (lm < ln) - lr *= (1 << 16); + lr += (1 << 16); lr += lm; } @@ -35,7 +35,7 @@ void test_le () { if (lm <= ln) - lr = lm * ((long)1 << 32); + lr = lm + ((long)1 << 32); else lr = lm; lr += lm; diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c index ac72d4d933a..743fd5e670e 100644 --- a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c @@ -29,7 +29,7 @@ void test_lez () { if (lm <= 0) - lr &= (1 << 16); + lr |= (1 << 16); lr += lm; } diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c new file mode 100644 index 00000000000..95887980cc5 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "maskeqz" } } */ +/* { dg-final { scan-assembler "masknez" } } */ + +extern long lm, ln, lr; + +void +test_and () +{ + if (lm < 0) + lr &= (1 << 16); + lr += lm; +} -- Gitee From b3e38880ce51505e7cd05eee04cbbc563c619df6 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 20 Nov 2025 08:58:47 +0000 Subject: [PATCH 3/3] LoongArch: avoid wrong if-conversions from cmove --- gcc/config/loongarch/loongarch.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 15230b91733..b44d52adff1 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -11200,14 +11200,11 @@ loongarch_c_mode_for_suffix (char suffix) static bool loongarch_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info) { - rtx src, dst; - enum rtx_code code; + enum rtx_class cls; for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn)) { - src = SET_SRC (single_set (insn)); - dst = SET_DEST (single_set (insn)); - code = GET_CODE (src); - if (REG_P (dst) && (code == LTU || code == LEU || code == GEU || code == GTU)) + cls = GET_RTX_CLASS (GET_CODE (SET_SRC (single_set (insn)))); + if ( cls == RTX_COMPARE || cls == RTX_COMM_COMPARE) return false; } -- Gitee