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

--- Comment #2 from Jeffrey A. Law <law at gcc dot gnu.org> ---
The pattern Andrew quoted I think is OK.  It "eats" the & 31 because that's
implicitly done by the hardware for the "w" forms of the shift instructions.  
The real problem is when we use that shift count in this pattern:

;; The logical-and against 0x1 implicitly extends the result.   So we can treat
;; an SImode bext as-if it's DImode without any explicit extension.
(define_insn "*bextdisi"
  [(set (match_operand:DI 0 "register_operand" "=r")
    (and:DI (subreg:DI (lshiftrt:SI
                         (match_operand:SI 1 "register_operand" "r")
                         (match_operand:QI 2 "register_operand" "r")) 0)
            (const_int 1)))]
  "TARGET_64BIT && TARGET_ZBS"
  "bext\t%0,%1,%2"
  [(set_attr "type" "bitmanip")]) 

It might seem like that pattern is safe, particularly since a shift count
outside 0..31 would be undefined behavior.  But the hw is going to use an & 63
mask rather than a & 31 mask for rv64.  So when the splitter corerctly
eliminates the & 31 and we match the bextdisi pattern we can get incorrect
results.

I need to ponder this a bit more.   But that's my take right now.

Reply via email to