From c2bb84be4a6e581bbf45891457ee632a07416982 Mon Sep 17 00:00:00 2001 From: Sudi Das Date: Fri, 18 Sep 2020 15:47:46 +0100 Subject: [PATCH] [PATCH 2/5][Arm] New pattern for CSINV instructions This patch adds a new pattern, *thumb2_csinv, for generating CSINV nstructions. This pattern relies on a few general changes that will be used throughout the following patches: - A new macro, TARGET_COND_ARITH, which is only true on 8.1-M Mainline and represents the existence of these conditional instructions. - A change to the cond exec hook, arm_have_conditional_execution, which now returns false if TARGET_COND_ARITH before reload. This allows for some ifcvt transformations when they would usually be disabled. I've written a rather verbose comment (with the risk of over-explaining) as it's a bit of a confusing change. - One new predicate. - *thumb2_movcond has been restricted to only match if !TARGET_COND_ARITH, otherwise it triggers undesirable combines. gcc/ChangeLog: * config/arm/arm.h (TARGET_COND_ARITH): New macro. * config/arm/arm.c (arm_have_conditional_execution): Return false if TARGET_COND_ARITH before reload. * config/arm/predicates.md (arm_comparison_operation): Returns true if comparing CC_REGNUM with constant zero. * config/arm/thumb2.md (*thumb2_csinv): New. (*thumb2_movcond): Don't match if TARGET_COND_ARITH. gcc/testsuite/ChangeLog: * gcc.target/arm/csinv-1.c: New test. Co-authored-by: Omar Tahir --- gcc/config/arm/arm.c | 17 ++++++++++++++--- gcc/config/arm/arm.h | 4 ++++ gcc/config/arm/predicates.md | 12 ++++++++++++ gcc/config/arm/thumb2.md | 16 +++++++++++++++- gcc/testsuite/gcc.target/arm/csinv-1.c | 23 +++++++++++++++++++++++ 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/csinv-1.c diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 932f90794c8..022ef6c3f1d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -29866,12 +29866,23 @@ arm_frame_pointer_required (void) return false; } -/* Only thumb1 can't support conditional execution, so return true if - the target is not thumb1. */ +/* Implement the TARGET_HAVE_CONDITIONAL_EXECUTION hook. + All modes except THUMB1 have conditional execution. + If we have conditional arithmetic, return false before reload to + enable some ifcvt transformations. */ static bool arm_have_conditional_execution (void) { - return !TARGET_THUMB1; + bool has_cond_exec, enable_ifcvt_trans; + + /* Only THUMB1 cannot support conditional execution. */ + has_cond_exec = !TARGET_THUMB1; + + /* Enable ifcvt transformations if we have conditional arithmetic, but only + before reload. */ + enable_ifcvt_trans = TARGET_COND_ARITH && !reload_completed; + + return has_cond_exec && !enable_ifcvt_trans; } /* The AAPCS sets the maximum alignment of a vector to 64 bits. */ diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 3887c51eebe..f4d3676c5bc 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -177,6 +177,10 @@ emission of floating point pcs attributes. */ #define TARGET_CRC32 (arm_arch_crc) +/* Thumb-2 but also has some conditional arithmetic instructions like csinc, + csinv, etc. */ +#define TARGET_COND_ARITH (arm_arch8_1m_main) + /* The following two macros concern the ability to execute coprocessor instructions for VFPv3 or NEON. TARGET_VFP3/TARGET_VFPD32 are currently only ever tested when we know we are generating for VFP hardware; we need diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 981eec520ba..2144520829c 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -485,6 +485,18 @@ (and (match_operand 0 "expandable_comparison_operator") (match_test "maybe_get_arm_condition_code (op) != ARM_NV"))) +(define_special_predicate "arm_comparison_operation" + (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered, + ordered,unlt,unle,unge,ungt") +{ + if (XEXP (op, 1) != const0_rtx) + return false; + rtx op0 = XEXP (op, 0); + if (!REG_P (op0) || REGNO (op0) != CC_REGNUM) + return false; + return maybe_get_arm_condition_code (op) != ARM_NV; +}) + (define_special_predicate "lt_ge_comparison_operator" (match_code "lt,ge")) diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 1a5f24e5276..d648ba1da53 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -938,6 +938,20 @@ (set_attr "type" "multiple")] ) +(define_insn "*thumb2_csinv" + [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r") + (if_then_else:SI + (match_operand 1 "arm_comparison_operation" "") + (not:SI (match_operand:SI 2 "arm_general_register_operand" "r, r")) + (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))] + "TARGET_COND_ARITH" + "@ + csinv\\t%0, %3, %2, %D1 + csinv\\t%0, zr, %2, %D1" + [(set_attr "type" "csel") + (set_attr "predicable" "no")] +) + (define_insn "*thumb2_movcond" [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts") (if_then_else:SI @@ -947,7 +961,7 @@ (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI") (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI"))) (clobber (reg:CC CC_REGNUM))] - "TARGET_THUMB2" + "TARGET_THUMB2 && !TARGET_COND_ARITH" "* if (GET_CODE (operands[5]) == LT && (operands[4] == const0_rtx)) diff --git a/gcc/testsuite/gcc.target/arm/csinv-1.c b/gcc/testsuite/gcc.target/arm/csinv-1.c new file mode 100644 index 00000000000..6b5383aa913 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/csinv-1.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arch_v8_1m_main_ok } */ +/* { dg-options "-O2 -march=armv8.1-m.main" } */ + +int +test_csinv32_condasn1(int w0, int w1, int w2, int w3) +{ + int w4; + + /* { dg-final { scan-assembler "csinv\tr\[0-9\]*.*ne" } } */ + w4 = (w0 == w1) ? ~w2 : w3; + return w4; +} + +int +test_csinv32_condasn2(int w0, int w1, int w2, int w3) +{ + int w4; + + /* { dg-final { scan-assembler "csinv\tr\[0-9\]*.*eq" } } */ + w4 = (w0 == w1) ? w3 : ~w2; + return w4; +} -- 2.30.2