https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124006

            Bug ID: 124006
           Summary: Improve another conditional sequence for RISC-V
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: law at gcc dot gnu.org
  Target Milestone: ---

This is using a generalized conditional move sequence when compiled with -O2
-march=rv64gcb_zicond (as noted by the pair of czero instructions with opposite
polarity).

It should be possible to eliminate one of the czero's by realizing this is just
a conditional IOR of a 32bit object.  So load a constant when the relevant
bit(s) set into a temporary GPR.  Conditionally zero the GPR, then IOR the
temporary with the original value.

typedef long int __ssize_t;
typedef __ssize_t ssize_t;
     typedef unsigned long UV;
     typedef signed char I8;
     typedef unsigned char U8;
     typedef int I32;
     typedef unsigned int U32;
struct regnode
{
  U8 type;
};
typedef struct regnode regnode;
struct scan_data_t;
typedef struct regnode_charclass regnode_charclass;
struct regnode_charclass_class;
typedef struct regnode_charclass_class regnode_charclass_posixl;
typedef struct regnode_ssc regnode_ssc;
typedef struct RExC_state_t RExC_state_t;
regnode *Perl_regnext (regnode * p);
     struct regnode_ssc
     {
     };
     extern const U8 PL_regkind[];
struct RExC_state_t
{
};
typedef struct scan_data_t
{
  I32 flags;
} scan_data_t;
ssize_t
S_study_chunk (RExC_state_t *pRExC_state, regnode **scanp,
               ssize_t *minlenp, ssize_t *deltap,
               regnode *last,
               scan_data_t *data,
               I32 stopparen,
               U32 recursed_depth,
               regnode_ssc *and_withp, U32 flags, U32 depth)
{
  regnode *scan = *scanp, *next;
  int is_inf = (flags & 0x0400) && (data->flags & 0x0040);
  int is_inf_internal = 0;
fake_study_recurse:
  {
    UV min_subtract = 0;
    _Bool unfolded_multi_char = (0);
    ssize_t mincount, maxcount, minnext, deltanext, pos_before = 0;
    I32 fl = 0, f = flags;
    regnode *const oscan = scan;
    regnode_ssc this_class;
    regnode_ssc *oclass = ((void *) 0);
    I32 next_is_eval = 0;
    switch (PL_regkind[((scan)->type)])
      {
      case 42:
        is_inf = is_inf_internal = 1;
        scan = Perl_regnext (scan);
        goto optimize_curly_tail;
      case 44:
      do_curly:
        data->flags &= ~(0x0080 | 0x0100 | 0x0200);
        if (is_inf)
          data->flags |= 0x0040;
      nogo:
      optimize_curly_tail:
      }
  }
finish:
}

And the relevant part of the resulting assembly:

        lw      a2,0(a5)
        andi    a2,a2,-897
        ori     a4,a2,64
        czero.eqz       a4,a4,a3
        czero.nez       a3,a2,a3
        addw    a4,a4,a3
        sw      a4,0(a5)
        ret

Reply via email to