Hi, The background and motivation of the patch are listed in the note of PATCH-1.
This patch changes the expander of ior/xor and force constant to a pseudo when it needs 2 insn. Also a combine and split pattern for ior/xor is defined. rtx_cost of ior insn is adjusted as now it may have 2 insns for certain constants. We need to check the cost of each operand. Bootstrapped and tested on powerpc64-linux BE and LE with no regressions. Thanks Gui Haochen ChangeLog 2023-03-14 Haochen Gui <guih...@linux.ibm.com> gcc/ * gcc/config/rs6000/rs6000.cc (rs6000_rtx_costs): Check the cost of each operand for IOR as it may have 2 insn for certain constants. * config/rs6000/rs6000.md (<code><mode>3): Put the second operand into register when it's a constant and need 2 ior/xor insns. (split for ior/xor): Remove. (*<code><mode>_2insn): New insn_and split pattern for 2-insn ior/xor. gcc/testsuite/ * gcc.target/powerpc/pr86106.c: New. patch.diff diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index b3a609f3aa3..f53daff547f 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -22081,10 +22081,6 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code, return false; case IOR: - /* FIXME */ - *total = COSTS_N_INSNS (1); - return true; - case CLZ: case XOR: case ZERO_EXTRACT: diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index dba41e3df90..0541f48c42a 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -3892,7 +3892,8 @@ (define_expand "<code><mode>3" DONE; } - if (non_logical_cint_operand (operands[2], <MODE>mode)) + if (non_logical_cint_operand (operands[2], <MODE>mode) + && !can_create_pseudo_p ()) { rtx tmp = ((!can_create_pseudo_p () || rtx_equal_p (operands[0], operands[1])) @@ -3907,15 +3908,17 @@ (define_expand "<code><mode>3" DONE; } - if (!reg_or_logical_cint_operand (operands[2], <MODE>mode)) + if (!logical_operand (operands[2], <MODE>mode)) operands[2] = force_reg (<MODE>mode, operands[2]); }) -(define_split - [(set (match_operand:GPR 0 "gpc_reg_operand") - (iorxor:GPR (match_operand:GPR 1 "gpc_reg_operand") - (match_operand:GPR 2 "non_logical_cint_operand")))] +(define_insn_and_split "*<code><mode>_2insn" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (iorxor:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") + (match_operand:GPR 2 "non_logical_cint_operand" "n")))] "" + "#" + "&& (!reload_completed || rtx_equal_p (operands[0], operands[1]))" [(set (match_dup 3) (iorxor:GPR (match_dup 1) (match_dup 4))) @@ -3933,7 +3936,8 @@ (define_split operands[4] = GEN_INT (hi); operands[5] = GEN_INT (lo); -}) +} + [(set_attr "length" "8")]) (define_insn "*bool<mode>3_imm" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") diff --git a/gcc/testsuite/gcc.target/powerpc/pr86106.c b/gcc/testsuite/gcc.target/powerpc/pr86106.c new file mode 100644 index 00000000000..71501476800 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr86106.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-prefixed" } */ + +unsigned int +foo (unsigned int val) +{ + unsigned int mask = 0x7f7f7f7f; + + return ~(((val & mask) + mask) | val | mask); +} + +/* { dg-final { scan-assembler-not {\maddis\M} } } */ +/* { dg-final { scan-assembler-not {\maddi\M} } } */ +/* { dg-final { scan-assembler-not {\moris\M} } } */