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

            Bug ID: 124007
           Summary: Improve branch-on-bit code generation
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: law at gcc dot gnu.org
  Target Milestone: ---

Marking as tree-optimization for now.  Depending on what is found during
investigation that could clearly change.

Compile with -O2 -march=rv64gcb_zicond on riscv64:

union tree_node;
typedef union tree_node *tree;
typedef const union tree_node *const_tree;
typedef struct
{
  unsigned long low;
  long high;
} double_int;
struct tree_base {
  unsigned int code : 16;

  unsigned side_effects_flag : 1;
  unsigned constant_flag : 1;
  unsigned addressable_flag : 1;
  unsigned volatile_flag : 1;
  unsigned readonly_flag : 1;
  unsigned unsigned_flag : 1;
  unsigned asm_written_flag: 1;
  unsigned nowarning_flag : 1;

  unsigned used_flag : 1;
  unsigned nothrow_flag : 1;
  unsigned static_flag : 1;
  unsigned public_flag : 1;
  unsigned private_flag : 1;
  unsigned protected_flag : 1;
  unsigned deprecated_flag : 1;
  unsigned saturating_flag : 1;

  unsigned default_def_flag : 1;
  unsigned lang_flag_0 : 1;
  unsigned lang_flag_1 : 1;
  unsigned lang_flag_2 : 1;
  unsigned lang_flag_3 : 1;
  unsigned lang_flag_4 : 1;
  unsigned lang_flag_5 : 1;
  unsigned lang_flag_6 : 1;

  unsigned visited : 1;
  unsigned packed_flag : 1;
  unsigned user_align : 1;

  unsigned spare : 13;




  unsigned address_space : 8;
};

struct tree_common {
  struct tree_base base;
  tree chain;
  tree type;
};
struct tree_int_cst {
  double_int int_cst;
};



union tree_node {
  struct tree_base base;
  struct tree_common common;
  struct tree_int_cst int_cst;
};

int tree_int_cst_sgn (const_tree);

int
tree_int_cst_lt (const_tree t1, const_tree t2)
{
  if (t1 == t2)
    return 0;

  if (((((t1)->common.type))->base.unsigned_flag) !=
((((t2)->common.type))->base.unsigned_flag))
    {
      int t1_sgn = tree_int_cst_sgn (t1);
      int t2_sgn = tree_int_cst_sgn (t2);

      if (t1_sgn < t2_sgn)
 return 1;
      else if (t1_sgn > t2_sgn)
 return 0;



    }
  else if (!((((t1)->common.type))->base.unsigned_flag))
    return ((((t1)->int_cst.int_cst).high) < (((t2)->int_cst.int_cst).high) ||
((((t1)->int_cst.int_cst).high) == (((t2)->int_cst.int_cst).h
igh) && (((t1)->int_cst.int_cst).low) < (((t2)->int_cst.int_cst).low)));

  return (((unsigned long) (((t1)->int_cst.int_cst).high) < (unsigned long)
(((t2)->int_cst.int_cst).high)) || (((unsigned long) (((t1)->int
_cst.int_cst).high) == (unsigned long) (((t2)->int_cst.int_cst).high)) &&
(((t1)->int_cst.int_cst).low) < (((t2)->int_cst.int_cst).low)));
}

Note the insns starting with the xor:

        xor     a5,a4,a5
        slli    a3,a5,42
        blt     a3,zero,.L19
        slli    a5,a4,42
        bge     a5,zero,.L20


It seems like the xor+2 slli instructions could be replaced with two bexti
instrutions (and corresponding adjustments to the branches).  My notes indicate
that LLVM handles this better than GCC.

Reply via email to