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

--- Comment #3 from chenglulu <chenglulu at loongson dot cn> ---
This involves the template <optab>di3_fake:
(define_insn "<optab>di3_fake"
  [(set (match_operand:DI 0 "register_operand" "=r,&r,&r")
        (sign_extend:DI
          (any_div:SI (match_operand:DI 1 "register_operand" "r,r,0")
                      (match_operand:DI 2 "register_operand" "r,r,r"))))]
  ""
{
  return loongarch_output_division ("<insn>.w<u>\t%0,%1,%2", operands);
}
  [(set_attr "type" "idiv")
   (set_attr "mode" "SI")
   (set (attr "enabled")
      (if_then_else
        (match_test "!!which_alternative == loongarch_check_zero_div_p()")
        (const_string "yes")
        (const_string "no")))])


I think there is a problem with the implementation of this template. 
First, the instructions generated in the template are [u]div.w[u], etc. The
description of such instructions in the instruction manual is that if the upper
32 bits are not extended by the 31st bit sign then the result is uncertain.
The second port, I don't know if the following is correct.
          (any_div:SI (match_operand:DI 1 "register_operand" "r,r,0")
                      (match_operand:DI 2 "register_operand" "r,r,r"))))]
I try to modify this template:
(define_insn "<optab>di3_fake"
  [(set (match_operand:DI 0 "register_operand" "=r,&r,&r")
        (sign_extend:DI
          (unspec:SI [(any_div:SI (match_operand:DI 1 "register_operand"
"r,r,0")
                      (match_operand:DI 2 "register_operand" "r,r,r"))]
           UNSPEC_ANY_DIV)))]
  ""
{
  return loongarch_output_division ("<insn>.w<u>\t%0,%1,%2", operands);
}
  [(set_attr "type" "idiv")
   (set_attr "mode" "SI")
   (set (attr "enabled")
      (if_then_else
        (match_test "!!which_alternative == loongarch_check_zero_div_p()")
        (const_string "yes")
        (const_string "no")))])

This problem can be solved. But I don't know if what I'm doing is correct...

Reply via email to