Hi --

I'm working on creating the cstore and cbranch templates
for the Xilinx MicroBlaze processor.  I've run into some
problems and an unexpected interaction with CSE processing.
Possibly, the insns I'm generating for comparisons are not
what the CSE optimization expects.

MicroBlaze has a bit unusual compare and branch architecture.
There are no condition flags; comparison results are stored in
a result register.

There's one branch instruction, which compares a register
with zero and branches based on condition (eq, ne, lt, gt, etc.).

There are a number of different instructions which can be used
for comparisons.  Regular instructions like sub or xor can be
used in some cases.  There are also cmp/cmpu instructions which
do a modified subtraction of signed and unsigned integers.
There are other comparison instructions for eq/ne which give
a 0 or one result.  The FP comparisons are all coupled with
a condition:  fcmp.eq, fcmp.lt, etc.

To generate the correct comparison instruction, I need to
know both the operands and the test condition.

It doesn't look like the (compare:CC ...) template can be
used.  Compare takes two operands and there is no place to
save the condition.

For comparisons, I'm generating insns like:

  (set (reg:CC rD) (eq:CC (reg:SI rA) (reg:SI rB))

followed by a branch:

  (if_then_else
     (eq:CC (reg:CC rD) (const_int 0))
     (label_ref xx)
     (pc)))

This looks OK and it appears to work reasonably well.  At
least without optimization.  CSE appears to be misinterpreting
the comparison insn and the code gets trashed.

This is taken from strchr.c in Newlib.  The preprocessed code
snippet is

   unsigned char c = i;

   if (!c)
      {
        while (((long)s & (sizeof (long) - 1)))
          {
            if (!*s)
              return (char *) s;
            s++;
          }
        . . .

Before CSE, this is the insn sequence:

(insn 90 89 91 2 .../strchr.c:66
  (set (reg/v:SI 137 [ c+-3 ])
       (zero_extend:SI (subreg:QI (reg/v:SI 244 [ i ]) 3))) 33

(insn 92 91 93 2 .../strchr.c:73
  (set (reg:SI 245)
       (const_int 0 [0x0])) 41

(insn 93 92 94 2 .../strchr.c:73
  (set (reg:CC 246)
       (eq:CC
           (reg/v:SI 137 [ c+-3 ])
           (reg:SI 245))) 71

(jump_insn 94 93 95 2 .../strchr.c:73
  (set (pc)
       (if_then_else
            (eq:CC
                (reg:CC 246)
                (const_int 0 [0x0]))
            (label_ref 112)
            (pc)))

This is the first if expression.   Note that reg 137 [c] is set to the
masked value of the search character i.  Reg 245 is set to zero, which
is used in the compare instruction in insn 93.

The while expression is

(insn 97 96 98 3 .../strchr.c:93
  (set (reg:SI 247)
       (and:SI
            (reg/v/f:SI 140 [ s ])
            (const_int 3 [0x3]))) 25

(insn 98 97 99 3 .../strchr.c:93
  (set (reg:SI 248)
       (const_int 0 [0x0])) 41

(insn 99 98 100 3 .../strchr.c:93
  (set (reg:CC 249)
       (eq:CC
           (reg:SI 247)
           (reg:SI 248))) 71

(jump_insn 100 99 101 3 .../strchr.c:93
  (set (pc)
       (if_then_else
            (eq:CC
                (reg:CC 249)
                (const_int 0 [0x0]))
            (label_ref 225)
            (pc))) 75

Reg 247 is set to the masked value of s, the string pointer.
Reg 248 is set to zero and is used in the compare in insn 99.

All of this looks OK to me.

There is an intermediate step where reg 248 is replaced by
reg 245, since both are set to zero.

Somehow, CSE is deciding that reg 137 is equal to zero and
translates insn 99 to

(insn 99 98 100 3 .../strchr.c:93
  (set (reg:CC 249)
       (eq:CC
           (reg:SI 247)
           (reg/v:SI 137 [ c+-3 ]))) 71

There is a REG_EQUAL note on this insn saying that it is equal
to const zero.  At this point, the code is hosed.

I've been stepping through CSE to figure out why it
decides that reg 137 is equal to zero, but haven't
found this yet.

(Yes, I do recognize that a comparison with zero can be
simplified into just the branch insn.  That's on my to do list.)

Questions:

  Is this a reasonable way to represent the comparisons?

  Are there other targets which save comparison results
  in registers and require the condition?

  Any suggestions on better ways to model the MicroBlaze
  comparison operations?

  Are there some restriction on using eq/ne/lt/... the
  way I am?

  Any suggestions on how to fix the problem in CSE?

--
Michael Eager    ea...@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

Reply via email to