This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RE: [PATCH 1/n] Add conditional compare support
- From: "Zhenqiang Chen" <zhenqiang dot chen at arm dot com>
- To: "'Richard Henderson'" <rth at redhat dot com>, "Richard Earnshaw" <Richard dot Earnshaw at arm dot com>, "'Richard Biener'" <richard dot guenther at gmail dot com>
- Cc: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 24 Oct 2013 16:11:04 +0800
- Subject: RE: [PATCH 1/n] Add conditional compare support
- Authentication-results: sourceware.org; auth=none
- References: <000001ce9e58$6dadf230$4909d690$ at arm dot com> <CAFiYyc25hLxrAnsOXbfqYo=Rsw_MDopxb66bygfac-CEsffOEw at mail dot gmail dot com> <521C9406 dot 6050901 at arm dot com> <CAFiYyc0zrBBUvRF0Vmv5PyvypfK75QYuc3D9AMTE+Fkh3nCq4Q at mail dot gmail dot com> <000001ceb453$ceaea3c0$6c0beb40$ at arm dot com> <523AC006 dot 5030706 at arm dot com> <000101ceb829$31ec9040$95c5b0c0$ at arm dot com> <000101cecf0b$148b33a0$3da19ae0$ at arm dot com> <5267F5DE dot 3050109 at redhat dot com>
> -----Original Message-----
> From: Richard Henderson [mailto:rth@redhat.com]
> Sent: Thursday, October 24, 2013 12:14 AM
> To: Zhenqiang Chen; Richard Earnshaw; 'Richard Biener'
> Cc: GCC Patches
> Subject: Re: [PATCH 1/n] Add conditional compare support
>
> > +static enum rtx_code
> > +arm_ccmode_to_code (enum machine_mode mode) {
> > + switch (mode)
> > + {
> > + case CC_DNEmode:
> > + return NE;
>
> Why would you need to encode comparisons in CCmodes?
> That looks like a mis-design to me.
The CCmodes are used to check whether the result of a previous conditional compare can combine with current compare. By changing it to rtx_code, I can reuse current code (arm_select_dominance_cc_mode_1) to check it.
The CCmodes are also used to emit the "condition code" for a conditional execution. E.g.
CC1 (CC_DGEmode) = CCMP (a >= 0, b >= 0)
==> cmp a, #0
cmpge b, #0
CC2 = CCMP ( CC1 != 0, c >= 0)
==> cmpge c, #0
The "ge" is from the mode of CC1 in "CC1 != 0". And the mode of CC2 is not necessary the same as CC1.
> > +Conditional compare instruction. Operand 2 and 5 are RTLs which
> > +perform two comparisons. Operand 1 is AND or IOR, which operates on
> > +the result of Operand 2 and 5. Operand 0 is the result of operand 1.
> > +
> > +A typical @code{ccmp} pattern looks like
> > +
> > +@smallexample
> > +(define_expand "ccmp"
> > + [(set (match_operand 0 "register_operand" "")
> > + (match_operator 1 ""
> > + [(match_operator:SI 2 "comparison_operator"
> > + [(match_operand:SI 3 "register_operand")
> > + (match_operand:SI 4 "register_operand")])
> > + (match_operator:SI 5 "comparison_operator"
> > + [(match_operand:SI 6 "register_operand")
> > + (match_operand:SI 7 "register_operand")])]))]
> > + ""
> > + "@dots{}")
> > +@end smallexample
>
> This documentation is inadequate. What sorts of input combinations are
> valid?
It depends on target. I will update it with your later comments on
* How to use cmp_hook and ccmp_hook to check valid combinations.
* How to write patterns to support more than two compares.
> How is the middle-end expected to compose more than two compares, as
> you describe in the mail? What mode should the middle-end use to allocate
> that output register?
The ccmp_candidate_p and expand_ccmp_expr_* are using recursively algorithm. One conditional compare can have two and only two compares. But if the operand is the result of a previous conditional compare, we have more than two compares. i.e.
CC1 = CCMP (CMP1, CMP2)
CC2 = CCMP (CC1 != 0, CMP3)
...
CCn = CCMP (CCn-1 != 0, CMPn+1)
And these are the representations we want to have on TREE/GIMPLE after front-end in my original patch.
http://gcc.1065356.n5.nabble.com/PATCH-1-n-Add-conditional-compare-support-td961953.html
> The only thing that makes a sort of sense to me is something akin to how the
> old cmp + bcc patterns worked. Except that's not especially clean, and
> there's a reason we got rid of them.
>
> I think the only clean interface is going to be a new hook or hooks. The
> return value of the hook with be an rtx akin to the PTEST value returned by
> prepare_cmp_insn. Which is a proper input to cbranch/cstore/etc.
>
> I might think that two hooks would be appropriate because it might make the
> ccmp hook easier. I.e.
>
> res = targetm.cmp_hook(...);
> while (more)
> res = targetm.ccmp_hook(res, ...);
>
> For combinations that can't be implemented with ccmp, the hook can return
> null.
Yip. This will be more efficient. I will update the patch.
In current patch, arm_select_dominance_cc_mode is the "cmp_hook" and arm_select_dominance_ccmp_mode is the "ccmp_hook".
> > +;; The first compare in this pattern is the result of a previous CCMP.
> > +;; We can not swap it. And we only need its flag.
> > +(define_insn "*ccmp_and"
> > + [(set (match_operand 6 "dominant_cc_register" "")
> > + (compare
> > + (and:SI
> > + (match_operator 4 "expandable_comparison_operator"
> > + [(match_operand 0 "dominant_cc_register" "")
> > + (match_operand:SI 1 "arm_add_operand" "")])
> > + (match_operator:SI 5 "arm_comparison_operator"
> > + [(match_operand:SI 2 "s_register_operand"
> > + "l,r,r,r,r")
> > + (match_operand:SI 3 "arm_add_operand"
> > + "lPy,rI,L,rI,L")]))
> > + (const_int 0)))]
> > + "TARGET_32BIT"
> > + "*
> > + {
> > + static const char *const cmp2[2] =
> > + {
> > + \"cmp%d4\\t%2, %3\",
> > + \"cmn%d4\\t%2, #%n3\"
> > + };
> > + static const char *const ite = \"it\\t%d4\";
> > + static const int cmp_idx[9] = {0, 0, 1, 0, 1};
> > +
> > + if (TARGET_THUMB2) {
> > + output_asm_insn (ite, operands);
> > + }
> > + output_asm_insn (cmp2[cmp_idx[which_alternative]], operands);
> > + return \"\";
> > + }"
>
> I would think simply splitting to a normal cond_exec insn post reload would
> be significantly cleaner than this.
The codes are copied from "*cmp_and ". I will try to simplify to normal cond_exec insn later.
> And for future reference, don't use '"*', just use '{'. That way you don't have
> to escape the embedded quotes, etc.
Thanks. I will update it.
-Zhenqiang