* [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns @ 2014-09-23 6:45 Zhenqiang Chen 2014-10-11 20:45 ` Richard Henderson 0 siblings, 1 reply; 6+ messages in thread From: Zhenqiang Chen @ 2014-09-23 6:45 UTC (permalink / raw) To: gcc-patches [-- Attachment #1: Type: text/plain, Size: 3312 bytes --] Ping? Patch is attached for easy to apply. Move the cstorecc4 pattern from "[PATCH, 10/10] aarch64: Handle ccmp in ifcvt to make it work with cmov" to this patch, since cmov optimization does not depend on that patch. Thanks! -Zhenqiang ChangeLog: 2014-09-23 Zhenqiang Chen <zhenqiang.chen@linaro.org> * config/aarch64/aarch64.md (cbranchcc4, *ccmp_and, *ccmp_ior, cstorecc4): New. > -----Original Message----- > From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches- > owner@gcc.gnu.org] On Behalf Of Zhenqiang Chen > Sent: Monday, June 23, 2014 3:01 PM > To: gcc-patches@gcc.gnu.org > Subject: [PATCH, 8/10] aarch64: ccmp insn patterns > > Hi, > > The patch adds two insn patterns for ccmp instructions. > > cbranchcc4 is introduced to generate optimized conditional branch without > an additional compare against the result of ccmp. > > OK for trunk? > > Thanks! > -Zhenqiang > > ChangeLog: > 2014-06-23 Zhenqiang Chen <zhenqiang.chen@linaro.org> > > * config/aarch64/aarch64.md (cbranchcc4): New. > (*ccmp_and, *ccmp_ior): New. > > diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md > index a4d8887..c25d940 100644 > --- a/gcc/config/aarch64/aarch64.md > +++ b/gcc/config/aarch64/aarch64.md > @@ -230,6 +230,52 @@ > " > ) > +(define_expand "cbranchcc4" > + [(set (pc) (if_then_else > + (match_operator 0 "aarch64_comparison_operator" > + [(match_operand 1 "cc_register" "") > + (const_int 0)]) > + (label_ref (match_operand 3 "" "")) > + (pc)))] > + "" > + " ") > + > +(define_insn "*ccmp_and" > + [(set (match_operand 6 "ccmp_cc_register" "") > + (compare > + (and:SI > + (match_operator 4 "aarch64_comparison_operator" > + [(match_operand 0 "ccmp_cc_register" "") > + (match_operand 1 "aarch64_plus_operand" "")]) > + (match_operator 5 "aarch64_comparison_operator" > + [(match_operand:GPI 2 "register_operand" "r,r,r") > + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) > + (const_int 0)))] > + "" > + { > + return aarch64_output_ccmp (operands, true, which_alternative); > + } > + [(set_attr "type" "alus_reg,alus_imm,alus_imm")] > +) > + > +(define_insn "*ccmp_ior" > + [(set (match_operand 6 "ccmp_cc_register" "") > + (compare > + (ior:SI > + (match_operator 4 "aarch64_comparison_operator" > + [(match_operand 0 "ccmp_cc_register" "") > + (match_operand 1 "aarch64_plus_operand" "")]) > + (match_operator 5 "aarch64_comparison_operator" > + [(match_operand:GPI 2 "register_operand" "r,r,r") > + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) > + (const_int 0)))] > + "" > + { > + return aarch64_output_ccmp (operands, false, which_alternative); > + } > + [(set_attr "type" "alus_reg,alus_imm,alus_imm")] > +) > + > (define_insn "*condjump" > [(set (pc) (if_then_else (match_operator 0 > "aarch64_comparison_operator" > [(match_operand 1 "cc_register" "") (const_int 0)]) > 57,1 [-- Attachment #2: 8-patterns.patch --] [-- Type: application/octet-stream, Size: 2322 bytes --] diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index c60038a..e213cbe 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -239,6 +239,52 @@ " ) +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "aarch64_comparison_operator" + [(match_operand 1 "cc_register" "") + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + " ") + +(define_insn "*ccmp_and" + [(set (match_operand 6 "ccmp_cc_register" "") + (compare + (and:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (match_operand 1 "aarch64_plus_operand" "")]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "" + { + return aarch64_output_ccmp (operands, true, which_alternative); + } + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] +) + +(define_insn "*ccmp_ior" + [(set (match_operand 6 "ccmp_cc_register" "") + (compare + (ior:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (match_operand 1 "aarch64_plus_operand" "")]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "" + { + return aarch64_output_ccmp (operands, false, which_alternative); + } + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] +) + (define_insn "*condjump" [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) @@ -2382,6 +2428,19 @@ " ) +(define_expand "cstorecc4" + [(set (match_operand:SI 0 "register_operand") + (match_operator 1 "aarch64_comparison_operator" + [(match_operand 2 "ccmp_cc_register") + (match_operand 3 "aarch64_plus_operand")]))] + "" +"{ + operands[3] = const0_rtx; + emit_insn (gen_rtx_SET (SImode, operands[0], operands[1])); + DONE; +}") + + (define_expand "cstore<mode>4" [(set (match_operand:SI 0 "register_operand" "") (match_operator:SI 1 "aarch64_comparison_operator" ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns 2014-09-23 6:45 [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns Zhenqiang Chen @ 2014-10-11 20:45 ` Richard Henderson 2014-10-27 7:50 ` Zhenqiang Chen 0 siblings, 1 reply; 6+ messages in thread From: Richard Henderson @ 2014-10-11 20:45 UTC (permalink / raw) To: Zhenqiang Chen, gcc-patches On 09/22/2014 11:45 PM, Zhenqiang Chen wrote: > +(define_expand "cbranchcc4" > + [(set (pc) (if_then_else > + (match_operator 0 "aarch64_comparison_operator" > + [(match_operand 1 "cc_register" "") > + (const_int 0)]) > + (label_ref (match_operand 3 "" "")) > + (pc)))] > + "" > + " ") Extra space. > +(define_insn "*ccmp_and" > + [(set (match_operand 6 "ccmp_cc_register" "") > + (compare > + (and:SI > + (match_operator 4 "aarch64_comparison_operator" > + [(match_operand 0 "ccmp_cc_register" "") > + (match_operand 1 "aarch64_plus_operand" "")]) > + (match_operator 5 "aarch64_comparison_operator" > + [(match_operand:GPI 2 "register_operand" "r,r,r") > + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) > + (const_int 0)))] > + "" > + { > + return aarch64_output_ccmp (operands, true, which_alternative); > + } > + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] > +) > + > +(define_insn "*ccmp_ior" > + [(set (match_operand 6 "ccmp_cc_register" "") > + (compare > + (ior:SI > + (match_operator 4 "aarch64_comparison_operator" > + [(match_operand 0 "ccmp_cc_register" "") > + (match_operand 1 "aarch64_plus_operand" "")]) > + (match_operator 5 "aarch64_comparison_operator" > + [(match_operand:GPI 2 "register_operand" "r,r,r") > + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) > + (const_int 0)))] > + "" > + { > + return aarch64_output_ccmp (operands, false, which_alternative); > + } > + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] Surely not aarch64_plus_operand for operand 1. That's a comparison with the flags register. Surely (const_int 0) is the only valid operand there. These could be combined with a code iterator, and thus there would be exactly one call to aarch64_output_ccmp, and thus inlined. Although... It seems to me that you don't need a function call at all. How about AND "@ ccmp\\t%<w>2, %<w>3, %K5, %m4 ccmp\\t%<w>2, %<w>3, %K5, %m4 ccmn\\t%<w>2, #%n3, %K5, %m4" IOR "@ ccmp\\t%<w>2, %<w>3, %k5, %M4 ccmp\\t%<w>2, %<w>3, %k5, %M4 ccmn\\t%<w>2, #%n3, %k5, %M4" where 'k' and 'K' are new print_operand codes that output the nzcv (or its inverse) integer for the comparison, much like 'm' and 'M' print the name of the comparison. r~ ^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns 2014-10-11 20:45 ` Richard Henderson @ 2014-10-27 7:50 ` Zhenqiang Chen 2014-10-27 15:58 ` Richard Henderson 0 siblings, 1 reply; 6+ messages in thread From: Zhenqiang Chen @ 2014-10-27 7:50 UTC (permalink / raw) To: 'Richard Henderson'; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 3076 bytes --] > -----Original Message----- > From: Richard Henderson [mailto:rth@redhat.com] > Sent: Sunday, October 12, 2014 4:12 AM > To: Zhenqiang Chen; gcc-patches@gcc.gnu.org > Subject: Re: [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns > > On 09/22/2014 11:45 PM, Zhenqiang Chen wrote: > > +(define_expand "cbranchcc4" > > + [(set (pc) (if_then_else > > + (match_operator 0 "aarch64_comparison_operator" > > + [(match_operand 1 "cc_register" "") > > + (const_int 0)]) > > + (label_ref (match_operand 3 "" "")) > > + (pc)))] > > + "" > > + " ") > > Extra space. Updated. > > +(define_insn "*ccmp_and" > > + [(set (match_operand 6 "ccmp_cc_register" "") > > + (compare > > + (and:SI > > + (match_operator 4 "aarch64_comparison_operator" > > + [(match_operand 0 "ccmp_cc_register" "") > > + (match_operand 1 "aarch64_plus_operand" "")]) > > + (match_operator 5 "aarch64_comparison_operator" > > + [(match_operand:GPI 2 "register_operand" "r,r,r") > > + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) > > + (const_int 0)))] > > + "" > > + { > > + return aarch64_output_ccmp (operands, true, which_alternative); > > + } > > + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] > > +) > > + > > +(define_insn "*ccmp_ior" > > + [(set (match_operand 6 "ccmp_cc_register" "") > > + (compare > > + (ior:SI > > + (match_operator 4 "aarch64_comparison_operator" > > + [(match_operand 0 "ccmp_cc_register" "") > > + (match_operand 1 "aarch64_plus_operand" "")]) > > + (match_operator 5 "aarch64_comparison_operator" > > + [(match_operand:GPI 2 "register_operand" "r,r,r") > > + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) > > + (const_int 0)))] > > + "" > > + { > > + return aarch64_output_ccmp (operands, false, which_alternative); > > + } > > + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] > > Surely not aarch64_plus_operand for operand 1. That's a comparison with > the flags register. Surely (const_int 0) is the only valid operand there. > > These could be combined with a code iterator, and thus there would be > exactly one call to aarch64_output_ccmp, and thus inlined. Although... > > It seems to me that you don't need a function call at all. How about > > AND > "@ > ccmp\\t%<w>2, %<w>3, %K5, %m4 > ccmp\\t%<w>2, %<w>3, %K5, %m4 > ccmn\\t%<w>2, #%n3, %K5, %m4" > > IOR > "@ > ccmp\\t%<w>2, %<w>3, %k5, %M4 > ccmp\\t%<w>2, %<w>3, %k5, %M4 > ccmn\\t%<w>2, #%n3, %k5, %M4" > > where 'k' and 'K' are new print_operand codes that output the nzcv (or its > inverse) integer for the comparison, much like 'm' and 'M' print the name of > the comparison. Updated with a bit change. + ccmp\\t%<w>2, %<w>3, %z5, %k4 + ccmp\\t%<w>2, %<w>3, %z5, %k4 + ccmn\\t%<w>2, #%n3, %z5, %k4" z/Z is the k/K as you suggested. I can not reuse m/M since they are special for cbranchcc (with CCMP). So I use new added k/K. Thanks! -Zhenqiang [-- Attachment #2: 7-8-ccmp-patterns.patch --] [-- Type: application/octet-stream, Size: 7001 bytes --] diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 1cf935a..3071aec 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3740,6 +3740,75 @@ bit_count (unsigned HOST_WIDE_INT value) return count; } +/* N Z C V. */ +#define AARCH64_CC_V 1 +#define AARCH64_CC_C (1 << 1) +#define AARCH64_CC_Z (1 << 2) +#define AARCH64_CC_N (1 << 3) + +/* N Z C V flags for ccmp. The first code is for AND op and the other + is for IOR op. Indexed by AARCH64_COND_CODE. */ +static const int aarch64_nzcv_codes[][2] = +{ + {AARCH64_CC_Z, 0}, /* EQ, Z == 1. */ + {0, AARCH64_CC_Z}, /* NE, Z == 0. */ + {AARCH64_CC_C, 0}, /* CS, C == 1. */ + {0, AARCH64_CC_C}, /* CC, C == 0. */ + {0, 0}, /* MI, not supported*/ + {0, 0}, /* PL, not supported*/ + {0, 0}, /* VS, not supported*/ + {0, 0}, /* VC, not supported*/ + {AARCH64_CC_C, AARCH64_CC_Z}, /* HI, C ==1 && Z == 0. */ + {AARCH64_CC_Z, AARCH64_CC_C}, /* LS, !(C == 1 && Z == 0). */ + {AARCH64_CC_N | AARCH64_CC_V, AARCH64_CC_N}, /* GE, N == V. */ + {AARCH64_CC_N, AARCH64_CC_N | AARCH64_CC_V}, /* LT, N != V. */ + {AARCH64_CC_N | AARCH64_CC_V, AARCH64_CC_Z}, /* GT, Z == 0 && N == V. */ + {AARCH64_CC_Z, AARCH64_CC_N | AARCH64_CC_V}, /* LE, !(Z == 0 && N == V). */ + {0, 0}, /* AL, not supported. */ + {0, 0}, /* NV, not supported. */ +}; + +static enum rtx_code +aarch64_ccmp_mode_to_code (enum machine_mode mode) +{ + switch (mode) + { + case CC_DNEmode: + return NE; + + case CC_DEQmode: + return EQ; + + case CC_DLEmode: + return LE; + + case CC_DGTmode: + return GT; + + case CC_DLTmode: + return LT; + + case CC_DGEmode: + return GE; + + case CC_DLEUmode: + return LEU; + + case CC_DGTUmode: + return GTU; + + case CC_DLTUmode: + return LTU; + + case CC_DGEUmode: + return GEU; + + default: + gcc_unreachable (); + } +} + + void aarch64_print_operand (FILE *f, rtx x, char code) { @@ -4104,6 +4173,81 @@ aarch64_print_operand (FILE *f, rtx x, char code) output_addr_const (asm_out_file, x); break; + case 'k': + { + int cond_code; + rtx op0 = XEXP (x, 0); + enum rtx_code mode_code; + /* Print a condition (eq, ne, etc) of ccmp. */ + + if (!COMPARISON_P (x) || !ccmp_cc_register (op0, GET_MODE (op0))) + { + output_operand_lossage ("invalid operand for '%%%c'", code); + return; + } + + mode_code = aarch64_ccmp_mode_to_code (GET_MODE (op0)); + cond_code = aarch64_get_condition_code_1 (CCmode, mode_code); + gcc_assert (cond_code >= 0); + fputs (aarch64_condition_codes[cond_code], f); + } + break; + + case 'K': + { + int cond_code; + rtx op0 = XEXP (x, 0); + enum rtx_code mode_code; + /* Print a condition (eq, ne, etc) of ccmp. */ + + if (!COMPARISON_P (x) || !ccmp_cc_register (op0, GET_MODE (op0))) + { + output_operand_lossage ("invalid operand for '%%%c'", code); + return; + } + + mode_code = aarch64_ccmp_mode_to_code (GET_MODE (op0)); + cond_code = aarch64_get_condition_code_1 (CCmode, mode_code); + gcc_assert (cond_code >= 0); + fputs (aarch64_condition_codes[AARCH64_INVERSE_CONDITION_CODE + (cond_code)], f); + } + break; + + case 'Z': + { + int cond_code; + /* Print nzcv. */ + + if (!COMPARISON_P (x)) + { + output_operand_lossage ("invalid operand for '%%%c'", code); + return; + } + + cond_code = aarch64_get_condition_code_1 (CCmode, GET_CODE (x)); + gcc_assert (cond_code >= 0); + asm_fprintf (f, "%d", aarch64_nzcv_codes[cond_code][0]); + } + break; + + case 'z': + { + int cond_code; + /* Print nzcv. */ + + if (!COMPARISON_P (x)) + { + output_operand_lossage ("invalid operand for '%%%c'", code); + return; + } + + cond_code = aarch64_get_condition_code_1 (CCmode, GET_CODE (x)); + gcc_assert (cond_code >= 0); + asm_fprintf (f, "%d", aarch64_nzcv_codes[cond_code][1]); + } + break; + default: output_operand_lossage ("invalid operand prefix '%%%c'", code); return; diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 74b554e..b8b5b60 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -239,6 +239,54 @@ " ) +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "aarch64_comparison_operator" + [(match_operand 1 "cc_register" "") + (match_operand 2 "const0_operand")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "") + +(define_insn "*ccmp_and" + [(set (match_operand 1 "ccmp_cc_register" "") + (compare + (and:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (const_int 0)]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "" + "@ + ccmp\\t%<w>2, %<w>3, %z5, %k4 + ccmp\\t%<w>2, %<w>3, %z5, %k4 + ccmn\\t%<w>2, #%n3, %z5, %k4" + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] +) + +(define_insn "*ccmp_ior" + [(set (match_operand 1 "ccmp_cc_register" "") + (compare + (ior:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (const_int 0)]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "" + "@ + ccmp\\t%<w>2, %<w>3, %Z5, %K4 + ccmp\\t%<w>2, %<w>3, %Z5, %K4 + ccmn\\t%<w>2, #%n3, %Z5, %K4" + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] +) + (define_insn "*condjump" [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) @@ -2395,6 +2443,18 @@ " ) +(define_expand "cstorecc4" + [(set (match_operand:SI 0 "register_operand") + (match_operator 1 "aarch64_comparison_operator" + [(match_operand 2 "ccmp_cc_register") + (match_operand 3 "const0_operand")]))] + "" +"{ + emit_insn (gen_rtx_SET (SImode, operands[0], operands[1])); + DONE; +}") + + (define_expand "cstore<mode>4" [(set (match_operand:SI 0 "register_operand" "") (match_operator:SI 1 "aarch64_comparison_operator" diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index f6fe58c..7129203 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -30,6 +30,11 @@ (ior (match_code "symbol_ref") (match_operand 0 "register_operand"))) +;; Return true if OP a (const_int 0) operand. +(define_predicate "const0_operand" + (and (match_code "const_int, const_double") + (match_test "op == CONST0_RTX (mode)"))) + (define_predicate "aarch64_ccmp_immediate" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), -31, 31)"))) ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns 2014-10-27 7:50 ` Zhenqiang Chen @ 2014-10-27 15:58 ` Richard Henderson 2014-10-29 10:42 ` Zhenqiang Chen 0 siblings, 1 reply; 6+ messages in thread From: Richard Henderson @ 2014-10-27 15:58 UTC (permalink / raw) To: Zhenqiang Chen; +Cc: gcc-patches On 10/27/2014 12:49 AM, Zhenqiang Chen wrote: > + {AARCH64_CC_Z, 0}, /* EQ, Z == 1. */ > + {0, AARCH64_CC_Z}, /* NE, Z == 0. */ > + {AARCH64_CC_C, 0}, /* CS, C == 1. */ > + {0, AARCH64_CC_C}, /* CC, C == 0. */ > + {0, 0}, /* MI, not supported*/ > + {0, 0}, /* PL, not supported*/ > + {0, 0}, /* VS, not supported*/ > + {0, 0}, /* VC, not supported*/ Why not go ahead and fill out the table? You know what needs to go in these slots, after all. > + {AARCH64_CC_C, AARCH64_CC_Z}, /* HI, C ==1 && Z == 0. */ > + {AARCH64_CC_Z, AARCH64_CC_C}, /* LS, !(C == 1 && Z == 0). */ > + {AARCH64_CC_N | AARCH64_CC_V, AARCH64_CC_N}, /* GE, N == V. */ > + {AARCH64_CC_N, AARCH64_CC_N | AARCH64_CC_V}, /* LT, N != V. */ > + {AARCH64_CC_N | AARCH64_CC_V, AARCH64_CC_Z}, /* GT, Z == 0 && N == V. */ > + {AARCH64_CC_Z, AARCH64_CC_N | AARCH64_CC_V}, /* LE, !(Z == 0 && N == V). */ Perhaps it's me, but does it make things clearer to reduce these? That is, for the compound conditions, we need not make both sub-conditions be false, only one of them. E.g. {AARCH64_CC_C, 0} /* HI, C ==1 && Z == 0. */ {0, AARCH64_CC_C} /* LS, !(C ==1 && Z == 0) */ {0, AARCH64_CC_V} /* GE, N == V */ {AARCH64_CC_V, 0} /* LT, N != V */ {0, AARCH64_CC_Z} /* GT, Z == 0 && N == V */ {AARCH64_CC_Z, 0} /* LE, !(Z == 0 && N == V) */ At which point it becomes blindingly obvious that while we can't compress the table with ~nczv, we can index it with reverse_comparison instead. > + case 'k': > + { > + int cond_code; > + rtx op0 = XEXP (x, 0); > + enum rtx_code mode_code; > + /* Print a condition (eq, ne, etc) of ccmp. */ > + > + if (!COMPARISON_P (x) || !ccmp_cc_register (op0, GET_MODE (op0))) > + { > + output_operand_lossage ("invalid operand for '%%%c'", code); > + return; > + } > + > + mode_code = aarch64_ccmp_mode_to_code (GET_MODE (op0)); > + cond_code = aarch64_get_condition_code_1 (CCmode, mode_code); > + gcc_assert (cond_code >= 0); > + fputs (aarch64_condition_codes[cond_code], f); > + } Is there a branch with all the patches applied? I can't look back at the modified aarch64_get_condition_code_1, but off-hand I can't think of why %m/%M wouldn't work. Surely aarch64_get_condition_code_1 (GET_MODE (op0), GET_CODE (x)) will yield the correct cond_code. If it didn't, then surely branches wouldn't work at all. These are not some magic new kind of conditions; they're exactly the same. r~ ^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns 2014-10-27 15:58 ` Richard Henderson @ 2014-10-29 10:42 ` Zhenqiang Chen 2014-10-29 14:32 ` Richard Henderson 0 siblings, 1 reply; 6+ messages in thread From: Zhenqiang Chen @ 2014-10-29 10:42 UTC (permalink / raw) To: 'Richard Henderson'; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 3229 bytes --] > -----Original Message----- > From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches- > owner@gcc.gnu.org] On Behalf Of Richard Henderson > Sent: Monday, October 27, 2014 11:47 PM > To: Zhenqiang Chen > Cc: gcc-patches@gcc.gnu.org > Subject: Re: [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns > > On 10/27/2014 12:49 AM, Zhenqiang Chen wrote: > > + {AARCH64_CC_Z, 0}, /* EQ, Z == 1. */ {0, AARCH64_CC_Z}, /* NE, Z > > + == 0. */ {AARCH64_CC_C, 0}, /* CS, C == 1. */ {0, AARCH64_CC_C}, > > + /* CC, C == 0. */ {0, 0}, /* MI, not supported*/ {0, 0}, /* PL, > > + not supported*/ {0, 0}, /* VS, not supported*/ {0, 0}, /* VC, not > > + supported*/ > > Why not go ahead and fill out the table? You know what needs to go in these > slots, after all. Updated. > > + {AARCH64_CC_C, AARCH64_CC_Z}, /* HI, C ==1 && Z == 0. */ > > + {AARCH64_CC_Z, AARCH64_CC_C}, /* LS, !(C == 1 && Z == 0). */ > > + {AARCH64_CC_N | AARCH64_CC_V, AARCH64_CC_N}, /* GE, N == V. */ > > + {AARCH64_CC_N, AARCH64_CC_N | AARCH64_CC_V}, /* LT, N != V. */ > > + {AARCH64_CC_N | AARCH64_CC_V, AARCH64_CC_Z}, /* GT, Z == 0 && N > == > > + V. */ {AARCH64_CC_Z, AARCH64_CC_N | AARCH64_CC_V}, /* LE, !(Z == > 0 > > + && N == V). */ > > Perhaps it's me, but does it make things clearer to reduce these? > That is, for the compound conditions, we need not make both sub-conditions > be false, only one of them. E.g. > > {AARCH64_CC_C, 0} /* HI, C ==1 && Z == 0. */ > {0, AARCH64_CC_C} /* LS, !(C ==1 && Z == 0) */ > {0, AARCH64_CC_V} /* GE, N == V */ > {AARCH64_CC_V, 0} /* LT, N != V */ > {0, AARCH64_CC_Z} /* GT, Z == 0 && N == V */ > {AARCH64_CC_Z, 0} /* LE, !(Z == 0 && N == V) */ > > At which point it becomes blindingly obvious that while we can't compress > the table with ~nczv, we can index it with reverse_comparison instead. Updated. > > + case 'k': > > + { > > + int cond_code; > > + rtx op0 = XEXP (x, 0); > > + enum rtx_code mode_code; > > + /* Print a condition (eq, ne, etc) of ccmp. */ > > + > > + if (!COMPARISON_P (x) || !ccmp_cc_register (op0, GET_MODE > (op0))) > > + { > > + output_operand_lossage ("invalid operand for '%%%c'", code); > > + return; > > + } > > + > > + mode_code = aarch64_ccmp_mode_to_code (GET_MODE (op0)); > > + cond_code = aarch64_get_condition_code_1 (CCmode, mode_code); > > + gcc_assert (cond_code >= 0); > > + fputs (aarch64_condition_codes[cond_code], f); > > + } > > Is there a branch with all the patches applied? I can't look back at the > modified aarch64_get_condition_code_1, but off-hand I can't think of > why %m/%M wouldn't work. Surely It's my fault. %m/%M work well in the new patch. And I add a check aarch64_ccmp_mode_to_code (GET_MODE (operands[1])) == GET_CODE (operands[5]) on the patterns to make sure that the compare and CC mode are aligned. Thanks! -Zhenqiang > aarch64_get_condition_code_1 (GET_MODE (op0), GET_CODE (x)) > > will yield the correct cond_code. If it didn't, then surely branches wouldn't > work at all. > > These are not some magic new kind of conditions; they're exactly the same. > > > r~ [-- Attachment #2: 7-8-ccmp-patterns.patch --] [-- Type: application/octet-stream, Size: 7096 bytes --] diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index c57a467..2334a30 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -313,4 +313,5 @@ extern void aarch64_final_prescan_insn (rtx_insn *); extern bool aarch64_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel); void aarch64_atomic_assign_expand_fenv (tree *, tree *, tree *); +int aarch64_ccmp_mode_to_code (enum machine_mode mode); #endif /* GCC_AARCH64_PROTOS_H */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 9799957..047f510 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3752,6 +3752,75 @@ bit_count (unsigned HOST_WIDE_INT value) return count; } +/* N Z C V. */ +#define AARCH64_CC_V 1 +#define AARCH64_CC_C (1 << 1) +#define AARCH64_CC_Z (1 << 2) +#define AARCH64_CC_N (1 << 3) + +/* N Z C V flags for ccmp. The first code is for AND op and the other + is for IOR op. Indexed by AARCH64_COND_CODE. */ +static const int aarch64_nzcv_codes[][2] = +{ + {AARCH64_CC_Z, 0}, /* EQ, Z == 1. */ + {0, AARCH64_CC_Z}, /* NE, Z == 0. */ + {AARCH64_CC_C, 0}, /* CS, C == 1. */ + {0, AARCH64_CC_C}, /* CC, C == 0. */ + {AARCH64_CC_N, 0}, /* MI, N == 1. */ + {0, AARCH64_CC_N}, /* PL, N == 0. */ + {AARCH64_CC_V, 0}, /* VS, V == 1. */ + {0, AARCH64_CC_V}, /* VC, V == 0. */ + {AARCH64_CC_C, 0}, /* HI, C ==1 && Z == 0. */ + {0, AARCH64_CC_C}, /* LS, !(C == 1 && Z == 0). */ + {0, AARCH64_CC_V}, /* GE, N == V. */ + {AARCH64_CC_V, 0}, /* LT, N != V. */ + {0, AARCH64_CC_Z}, /* GT, Z == 0 && N == V. */ + {AARCH64_CC_Z, 0}, /* LE, !(Z == 0 && N == V). */ + {0, 0}, /* AL, Any. */ + {0, 0}, /* NV, Any. */ +}; + +int +aarch64_ccmp_mode_to_code (enum machine_mode mode) +{ + switch (mode) + { + case CC_DNEmode: + return NE; + + case CC_DEQmode: + return EQ; + + case CC_DLEmode: + return LE; + + case CC_DGTmode: + return GT; + + case CC_DLTmode: + return LT; + + case CC_DGEmode: + return GE; + + case CC_DLEUmode: + return LEU; + + case CC_DGTUmode: + return GTU; + + case CC_DLTUmode: + return LTU; + + case CC_DGEUmode: + return GEU; + + default: + gcc_unreachable (); + } +} + + void aarch64_print_operand (FILE *f, rtx x, char code) { @@ -4116,6 +4185,40 @@ aarch64_print_operand (FILE *f, rtx x, char code) output_addr_const (asm_out_file, x); break; + case 'K': + { + int cond_code; + /* Print nzcv. */ + + if (!COMPARISON_P (x)) + { + output_operand_lossage ("invalid operand for '%%%c'", code); + return; + } + + cond_code = aarch64_get_condition_code_1 (CCmode, GET_CODE (x)); + gcc_assert (cond_code >= 0); + asm_fprintf (f, "%d", aarch64_nzcv_codes[cond_code][0]); + } + break; + + case 'k': + { + int cond_code; + /* Print nzcv. */ + + if (!COMPARISON_P (x)) + { + output_operand_lossage ("invalid operand for '%%%c'", code); + return; + } + + cond_code = aarch64_get_condition_code_1 (CCmode, GET_CODE (x)); + gcc_assert (cond_code >= 0); + asm_fprintf (f, "%d", aarch64_nzcv_codes[cond_code][1]); + } + break; + default: output_operand_lossage ("invalid operand prefix '%%%c'", code); return; diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 341c26f..df2f591 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -245,6 +245,54 @@ " ) +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "aarch64_comparison_operator" + [(match_operand 1 "cc_register" "") + (match_operand 2 "const0_operand")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "") + +(define_insn "*ccmp_and" + [(set (match_operand 1 "ccmp_cc_register" "") + (compare + (and:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (const_int 0)]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "aarch64_ccmp_mode_to_code (GET_MODE (operands[1])) == GET_CODE (operands[5])" + "@ + ccmp\\t%<w>2, %<w>3, %k5, %m4 + ccmp\\t%<w>2, %<w>3, %k5, %m4 + ccmn\\t%<w>2, #%n3, %k5, %m4" + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] +) + +(define_insn "*ccmp_ior" + [(set (match_operand 1 "ccmp_cc_register" "") + (compare + (ior:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (const_int 0)]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "aarch64_ccmp_mode_to_code (GET_MODE (operands[1])) == GET_CODE (operands[5])" + "@ + ccmp\\t%<w>2, %<w>3, %K5, %M4 + ccmp\\t%<w>2, %<w>3, %K5, %M4 + ccmn\\t%<w>2, #%n3, %K5, %M4" + [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] +) + (define_insn "*condjump" [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) @@ -2401,6 +2449,18 @@ " ) +(define_expand "cstorecc4" + [(set (match_operand:SI 0 "register_operand") + (match_operator 1 "aarch64_comparison_operator" + [(match_operand 2 "ccmp_cc_register") + (match_operand 3 "const0_operand")]))] + "" +"{ + emit_insn (gen_rtx_SET (SImode, operands[0], operands[1])); + DONE; +}") + + (define_expand "cstore<mode>4" [(set (match_operand:SI 0 "register_operand" "") (match_operator:SI 1 "aarch64_comparison_operator" @@ -2549,15 +2609,19 @@ (match_operand:ALLI 3 "register_operand" "")))] "" { - rtx ccreg; enum rtx_code code = GET_CODE (operands[1]); if (code == UNEQ || code == LTGT) FAIL; - ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0), - XEXP (operands[1], 1)); - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); + if (!ccmp_cc_register (XEXP (operands[1], 0), + GET_MODE (XEXP (operands[1], 0)))) + { + rtx ccreg; + ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); + } } ) diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index f6fe58c..7129203 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -30,6 +30,11 @@ (ior (match_code "symbol_ref") (match_operand 0 "register_operand"))) +;; Return true if OP a (const_int 0) operand. +(define_predicate "const0_operand" + (and (match_code "const_int, const_double") + (match_test "op == CONST0_RTX (mode)"))) + (define_predicate "aarch64_ccmp_immediate" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), -31, 31)"))) ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns 2014-10-29 10:42 ` Zhenqiang Chen @ 2014-10-29 14:32 ` Richard Henderson 0 siblings, 0 replies; 6+ messages in thread From: Richard Henderson @ 2014-10-29 14:32 UTC (permalink / raw) To: Zhenqiang Chen; +Cc: gcc-patches On 10/29/2014 03:37 AM, Zhenqiang Chen wrote: > It's my fault. %m/%M work well in the new patch. > > And I add a check > > aarch64_ccmp_mode_to_code (GET_MODE (operands[1])) == GET_CODE (operands[5]) > > on the patterns to make sure that the compare and CC mode are aligned. Looks good. r~ ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-10-29 14:30 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-09-23 6:45 [Ping] [PATCH, 8/10] aarch64: ccmp insn patterns Zhenqiang Chen 2014-10-11 20:45 ` Richard Henderson 2014-10-27 7:50 ` Zhenqiang Chen 2014-10-27 15:58 ` Richard Henderson 2014-10-29 10:42 ` Zhenqiang Chen 2014-10-29 14:32 ` Richard Henderson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).