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

            Bug ID: 61503
           Summary: RTL representation of i386 shrdl instruction is
                    incorrect?
           Product: gcc
           Version: 4.10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nirhasabnis at gmail dot com

Hello,

I was studying i386 machine description for my research purpose,
and I stumbled upon following MD entry for 'shrdl' x86 instruction.
It is obtained from the most recent i386.md file.

(define_insn "x86_shrd"
  [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m")
        (ior:SI (ashiftrt:SI (match_dup 0)
 (match_operand:QI 2 "nonmemory_operand" "Ic"))
(ashift:SI (match_operand:SI 1 "register_operand" "r")
 (minus:QI (const_int 32) (match_dup 2)))))
   (clobber (reg:CC FLAGS_REG))]
  ""
  "shrd{l}\t{%s2%1, %0|%0, %1, %2}"
  [(set_attr "type" "ishift")
   (set_attr "prefix_0f" "1")
   (set_attr "mode" "SI")
   (set_attr "pent_pair" "np")
   (set_attr "athlon_decode" "vector")
   (set_attr "amdfam10_decode" "vector")
   (set_attr "bdver1_decode" "vector")])

It seems to me that the RTL representation for 'shrdl' is incorrect.

Semantics of shrdl instruction as per Intel manual is:
"The instruction shifts the first operand (destination operand) to the right
the number of bits specified by the third operand (count operand).
The second operand (source operand) provides bits to shift in from the
left (starting with the most significant bit of the destination operand)."
And the way RTL does it is by inclusive-or of arithmetically
right-shifted destination and left-shifted source operand.

But the problem is that: in case of a destination (reg/mem) containing
negative value, arithmetically right-shifted destination will have top bits
set to 1. Inclusive-or with such a value is going to generate a
result with top bits set to 1 instead of moving contents of source
into top bits of destination.

E.g., when ebx = b72f60d0, ebp = bfcbd2c8
    shrdl $16, %ebp, %ebx (ebx is dest, ebp is src)
produces 0xd2c8b72f in ebx.
But the corresponding RTL produces 0xffffb72f in ebx.

So it seems to me that instead of 'ashiftrt', RTL should have 'lshiftrt'.

Filing a bug as per the discussion at
https://gcc.gnu.org/ml/gcc/2014-06/msg00070.html

Reply via email to