On Tue, May 21, 2024 at 5:46 AM Alexander Monakov <amona...@ispras.ru> wrote:
>
>
> Hello!
>
> I looked at ternlog a bit last year, so I'd like to offer some drive-by
> comments. If you want to tackle them in a follow-up patch, or leave for
> someone else to handle, please let me know.
>
> On Fri, 17 May 2024, Roger Sayle wrote:
>
> > This revised patch has been tested on x86_64-pc-linux-gnu with make 
> > bootstrap
> > and make -k check, both with and without --target_board=unix{-m32}
> > with no new failures.  Ok for mainline?
>
> Just to make sure: no new tests for the new tricks?
>
> > --- a/gcc/config/i386/i386-expand.cc
> > +++ b/gcc/config/i386/i386-expand.cc
> > +/* Determine the ternlog immediate index that implements 3-operand
> > +   ternary logic expression OP.  This uses and modifies the 3 element
> > +   array ARGS to record and check the leaves, either 3 REGs, or 2 REGs
> > +   and MEM.  Returns an index between 0 and 255 for a valid ternlog,
> > +   or -1 if the expression isn't suitable.  */
> > +
> > +int
> > +ix86_ternlog_idx (rtx op, rtx *args)
> > +{
> > +  int idx0, idx1;
> > +
> > +  if (!op)
> > +    return -1;
> > +
> > +  switch (GET_CODE (op))
> > +    {
> > +    case REG:
> > +      if (!args[0])
> > +     {
> > +       args[0] = op;
> > +       return 0xf0;
>
> From readability perspective, I wonder if it's nicer to have something like
>
> enum {
>   TERNLOG_A = 0xf0,
>   TERNLOG_B = 0xcc,
>   TERNLOG_C = 0xaa
> }
>
> and then use them to build the immediates.
>
> > +     }
> > +      if (REGNO (op) == REGNO (args[0]))
> > +     return 0xf0;
> > +      if (!args[1])
> > +     {
> > +       args[1] = op;
> > +       return 0xcc;
> > +     }
> [snip]
> > +
> > +/* Return TRUE if OP (in mode MODE) is the leaf of a ternary logic
> > +   expression, such as a register or a memory reference.  */
> > +
> > +bool
> > +ix86_ternlog_leaf_p (rtx op, machine_mode mode)
> > +{
> > +  /* We can't use memory_operand here, as it may return a different
> > +     value before and after reload (for volatile MEMs) which creates
> > +     problems splitting instructions.  */
> > +  return register_operand (op, mode)
> > +      || MEM_P (op)
> > +      || GET_CODE (op) == CONST_VECTOR
> > +      || bcst_mem_operand (op, mode);
>
> Did your editor automatically indent this correctly for you? I think
> usually such expressions have outer parenthesis.
>
> > +}
> [snip]
> > +/* Expand a 3-operand ternary logic expression.  Return TARGET. */
> > +rtx
> > +ix86_expand_ternlog (machine_mode mode, rtx op0, rtx op1, rtx op2, int idx,
> > +                  rtx target)
> > +{
> > +  rtx tmp0, tmp1, tmp2;
> > +
> > +  if (!target)
> > +    target = gen_reg_rtx (mode);
> > +
> > +  /* Canonicalize ternlog index for degenerate (duplicated) operands.  */
>
> But this only canonicalizes the case of triplicated operands, and does nothing
> if two operands are duplicates of each other, and the third is distinct.
> Handling that would complicate the already large patch a lot though.
I think it's handled below,
  tmp0 = register_operand (op0, mode) ? op0 : force_reg (mode, op0);
  if (GET_MODE (tmp0) != mode)
    tmp0 = gen_lowpart (mode, tmp0);

  if (!op1 || rtx_equal_p (op0, op1))  ---- here
    tmp1 = copy_rtx (tmp0);
  else if (!register_operand (op1, mode))
    tmp1 = force_reg (mode, op1);
  else
    tmp1 = op1;
  if (GET_MODE (tmp1) != mode)
    tmp1 = gen_lowpart (mode, tmp1);

  if (!op2 || rtx_equal_p (op0, op2)) ---------- and here.
    tmp2 = copy_rtx (tmp0);
  else if (rtx_equal_p (op1, op2))
    tmp2 = copy_rtx (tmp1);
  else if (GET_CODE (op2) == CONST_VECTOR)
    {
      if (GET_MODE (op2) != mode)
op2 = gen_lowpart (mode, op2);
      tmp2 = ix86_gen_bcst_mem (mode, op2);
      if (!tmp2)
{
  tmp2 = validize_mem (force
>
> > +  if (rtx_equal_p (op0, op1) && rtx_equal_p (op0, op2))
> > +    switch (idx & 0x81)
> > +      {
> > +      case 0x00:
> > +     idx = 0x00;
> > +     break;
> > +      case 0x01:
> > +     idx = 0x0f;
> > +     break;
> > +      case 0x80:
> > +     idx = 0xf0;
> > +     break;
> > +      case 0x81:
> > +     idx = 0xff;
> > +     break;
> > +      }
> > +
> > +  switch (idx & 0xff)
> > +    {
> > +    case 0x00:
> > +      if ((!op0 || !side_effects_p (op0))
> > +          && (!op1 || !side_effects_p (op1))
> > +          && (!op2 || !side_effects_p (op2)))
> > +        {
> > +       emit_move_insn (target, CONST0_RTX (mode));
> > +       return target;
> > +     }
> > +      break;
> > +
> > +    case 0x0a: /* ~a&c */
>
> With the enum idea above, this could be 'case ~TERNLOG_A & TERNLOG_C', etc.
>
> Alexander



-- 
BR,
Hongtao

Reply via email to