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

            Bug ID: 93171
           Summary: rldimi is sometimes not produced because combine gets
                    in the way
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: enhancement
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: pinskia at gcc dot gnu.org
  Target Milestone: ---
            Target: powerpc64-linux-gnu

Take:
typedef unsigned long long uint64_t;
typedef uint64_t cvmx_pow_tag_type_t;
typedef uint64_t cvmx_pow_tag_op_t;
typedef union
{
    uint64_t u64;
    struct
    {

        uint64_t no_sched : 1;
        uint64_t unused : 2;
        uint64_t index :13;
        cvmx_pow_tag_op_t op : 4;
        uint64_t unused2 : 2;
        uint64_t qos : 3;
        uint64_t grp : 4;
        cvmx_pow_tag_type_t type : 3;
        uint64_t tag :32;
    } s_cn38xx;
    struct {

        uint64_t no_sched : 1;
        cvmx_pow_tag_op_t op : 4;
        uint64_t unused1 : 16;
        uint64_t grp : 6;
        uint64_t unused3 : 3;
        cvmx_pow_tag_type_t type : 2;
        uint64_t tag :32;
    } s_cn68xx_other;

} cvmx_pow_tag_req_t;

int c;

#define CVMX_POW_TAG_OP_SWTAG 0

void f(uint64_t *a, int tag, int tag_type)
{
  cvmx_pow_tag_req_t tag_req;
  tag_req.u64 = 0;
  if (c)
    {
      tag_req.s_cn68xx_other.op = 0;
      tag_req.s_cn68xx_other.tag = tag;
  asm("":"+r"(tag_req.u64));
      tag_req.s_cn68xx_other.type = tag_type;
    }
  else
    {
      tag_req.s_cn38xx.op = 0;
      tag_req.s_cn38xx.tag = tag;
//  asm("":"+r"(tag_req.u64));
      tag_req.s_cn38xx.type = tag_type;
    }

  *a = tag_req.u64;
}
--- CUT ---
On the path which contains the asm, we get:
        rldimi 4,5,32,30

While on the other path, we get:
        rldic 5,5,32,29
        or 4,4,5

NOTE the asm is just there to force combine not to happen :).

Reply via email to