This patch adds support for negate, absolute value, and negative absolute value. It does this by doing IOR, XOR, and ANDC on the BF/HF values. In order to do this optimization, it also needs to define the logical instructions for HFmode and BFmode.
2025-11-05 Michael Meissner <[email protected]> gcc/ * config/rs6000/float16.md (neg<mode>2): Add BFmode/HFmode negate, absolute value and negative absolute value operations. Add logical insns operating on BFmode/HFmode. (abs<mode>2): Likewise. (nabs<mode>2): Likewise. (and<mode>3): Likewise. (ior<mode>): Likewise. (xor<mode>3): Likewise. (nor<mode>3): Likewise. (andn<mode>3): Likewise. (eqv<mode>3): Likewise. (nand<mode>3): Likewise. (iorn<mode>3): Likewise. (bool<mode>3): Likewise. (boolc<mode>3): Likewise. (boolcc<mode>): Likewise. --- gcc/config/rs6000/float16.md | 213 +++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md index c828b5711fb..273848b28ed 100644 --- a/gcc/config/rs6000/float16.md +++ b/gcc/config/rs6000/float16.md @@ -472,3 +472,216 @@ (define_expand "fixuns_trunc<FP16_HW:mode><GPR:mode>2" emit_insn (gen_fixuns_truncdf<GPR:mode>2 (operands[0], df_tmp)); DONE; }) + +;; Negate 16-bit floating point by XOR with -0.0. + +(define_insn_and_split "neg<mode>2" + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,?wr") + (neg:FP16 (match_operand:FP16 1 "gpc_reg_operand" "wa,wr"))) + (clobber (match_scratch:FP16 2 "=&wa,&r"))] + "" + "#" + "&& 1" + [(set (match_dup 2) + (match_dup 3)) + (set (match_dup 0) + (xor:FP16 (match_dup 1) + (match_dup 2)))] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (<MODE>mode); + + REAL_VALUE_TYPE dconst; + + gcc_assert (real_from_string (&dconst, "-0.0") == 0); + + rtx rc = const_double_from_real_value (dconst, <MODE>mode); + if (!TARGET_PREFIXED) + rc = force_const_mem (<MODE>mode, rc); + + operands[3] = rc; +} + [(set_attr "type" "veclogical,integer") + (set_attr "length" "16")]) + +;; 16-bit floating point absolute value + +(define_insn_and_split "abs<mode>2" + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,?wr") + (abs:FP16 + (match_operand:FP16 1 "gpc_reg_operand" "wa,wr"))) + (clobber (match_scratch:FP16 2 "=&wa,&r"))] + "" + "#" + "&& 1" + [(set (match_dup 2) + (match_dup 3)) + (set (match_dup 0) + (and:FP16 (match_dup 1) + (not:FP16 (match_dup 2))))] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (<MODE>mode); + + REAL_VALUE_TYPE dconst; + + gcc_assert (real_from_string (&dconst, "-0.0") == 0); + + rtx rc = const_double_from_real_value (dconst, <MODE>mode); + + if (!TARGET_PREFIXED) + rc = force_const_mem (<MODE>mode, rc); + + operands[3] = rc; +} + [(set_attr "type" "veclogical,integer") + (set_attr "length" "16")]) + +;; 16-bit negative floating point absolute value + +(define_insn_and_split "*nabs<mode>2" + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,?wr") + (neg:FP16 + (abs:FP16 + (match_operand:FP16 1 "gpc_reg_operand" "wa,wr")))) + (clobber (match_scratch:FP16 2 "=&wa,&r"))] + "" + "#" + "&& 1" + [(set (match_dup 2) + (match_dup 3)) + (set (match_dup 0) + (ior:FP16 (match_dup 1) + (match_dup 2)))] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (<MODE>mode); + + REAL_VALUE_TYPE dconst; + + gcc_assert (real_from_string (&dconst, "-0.0") == 0); + rtx rc = const_double_from_real_value (dconst, <MODE>mode); + + if (!TARGET_PREFIXED) + rc = force_const_mem (<MODE>mode, rc); + + operands[3] = rc; +} + [(set_attr "type" "veclogical,integer") + (set_attr "length" "16")]) + +;; Add logical operations for 16-bit floating point types that are used +;; for things like negate, abs, and negative abs. Possibly in the +;; future we might need logical operators for extracting exponents and +;; mantissas. +(define_expand "and<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (and:FP16 (match_operand:FP16 1 "gpc_reg_operand") + (match_operand:FP16 2 "gpc_reg_operand")))] + "" + "") + +(define_expand "ior<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (ior:FP16 (match_operand:FP16 1 "gpc_reg_operand") + (match_operand:FP16 2 "gpc_reg_operand")))] + "" + "") + +(define_expand "xor<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (xor:FP16 (match_operand:FP16 1 "gpc_reg_operand") + (match_operand:FP16 2 "gpc_reg_operand")))] + "" + "") + +(define_expand "nor<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (and:FP16 + (not:FP16 (match_operand:FP16 1 "gpc_reg_operand")) + (not:FP16 (match_operand:FP16 2 "gpc_reg_operand"))))] + "" + "") + +(define_expand "andn<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (and:FP16 + (not:FP16 (match_operand:FP16 2 "gpc_reg_operand")) + (match_operand:FP16 1 "gpc_reg_operand")))] + "" + "") + +(define_expand "eqv<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (not:FP16 + (xor:FP16 (match_operand:FP16 1 "gpc_reg_operand") + (match_operand:FP16 2 "gpc_reg_operand"))))] + "" + "") + +;; Rewrite nand into canonical form +(define_expand "nand<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (ior:FP16 + (not:FP16 (match_operand:FP16 1 "gpc_reg_operand")) + (not:FP16 (match_operand:FP16 2 "gpc_reg_operand"))))] + "" + "") + +;; The canonical form is to have the negated element first, so we need to +;; reverse arguments. +(define_expand "iorn<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand") + (ior:FP16 + (not:FP16 (match_operand:FP16 2 "gpc_reg_operand")) + (match_operand:FP16 1 "gpc_reg_operand")))] + "" + "") + +;; AND, IOR, and XOR insns. Unlike HImode operations prefer using +;; floating point/vector registers over GPRs. +(define_insn "*bool<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,r") + (match_operator:FP16 3 "boolean_operator" + [(match_operand:FP16 1 "gpc_reg_operand" "wa,r") + (match_operand:FP16 2 "gpc_reg_operand" "wa,r")]))] + "" + "@ + xxl%q3 %x0,%x1,%x2 + %q3 %0,%1,%2" + [(set_attr "type" "veclogical,logical")]) + +;; ANDC, IORC, and EQV insns. +(define_insn "*boolc<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,r") + (match_operator:FP16 3 "boolean_operator" + [(not:FP16 (match_operand:FP16 2 "gpc_reg_operand" "wa,r")) + (match_operand:FP16 1 "gpc_reg_operand" "wa,r")]))] + "" + "@ + xxl%q3 %x0,%x1,%x2 + %q3 %0,%1,%2" + [(set_attr "type" "veclogical,logical")]) + +(define_insn "*boolc<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,r") + (match_operator:FP16 3 "boolean_operator" + [(match_operand:FP16 1 "gpc_reg_operand" "wa,r") + (not:FP16 (match_operand:FP16 2 "gpc_reg_operand" "wa,r"))]))] + "" + "@ + xxl%q3 %x0,%x1,%x2 + %q3 %0,%1,%2" + [(set_attr "type" "veclogical,logical")]) + +;; NOR and NAND insns. +(define_insn "*boolcc<mode>3" + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,r") + (match_operator:FP16 3 "boolean_operator" + [(not:FP16 (match_operand:FP16 1 "gpc_reg_operand" "wa,r")) + (not:FP16 (match_operand:FP16 2 "gpc_reg_operand" "wa,r"))]))] + "" + "@ + xxl%q3 %x0,%x1,%x2 + %q3 %0,%1,%2" + [(set_attr "type" "veclogical,logical")]) -- 2.51.1 -- Michael Meissner, IBM PO Box 98, Ayer, Massachusetts, USA, 01432 email: [email protected]
