"<bit_optab>i\t%0,%1,%S2"
[(set_attr "type" "bitmanip")])
+;; This form can be created by combine.
+(define_insn "*xor_for_plus_minint"
+ [(set (match_operand:X 0 "register_operand" "=r")
+ (plus:X (match_operand:X 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand")))]
+ "(TARGET_ZBS
+ && (INTVAL (operands[2])
+ == sext_hwi ((HOST_WIDE_INT_1U << (BITS_PER_WORD - 1)), BITS_PER_WORD)))"
+ "binvi\t%0,%1,%S2"
+ [(set_attr "type" "bitmanip")])
+
;; We can easily handle zero extensions
(define_split
[(set (match_operand:DI 0 "register_operand")
if (SMALL_OPERAND (INTVAL (operands[2])))
return false;
- int budget1 = riscv_const_insns (operands[2], true);
- int budget2 = riscv_const_insns (GEN_INT (-INTVAL (operands[2])), true);
-
HOST_WIDE_INT ival = INTVAL (operands[2]);
+ int budget1 = riscv_integer_cost (ival, true);
+ int budget2 = riscv_integer_cost (-ival, true);
+
+ /* If the constant is MIN_INT for the target, then it's just a bit flip
+ of the highest bit. */
+ HOST_WIDE_INT sextval = sext_hwi (HOST_WIDE_INT_1U << (BITS_PER_WORD - 1),
+ BITS_PER_WORD);
+ if (TARGET_ZBS && ival == sextval)
+ {
+ rtx x = gen_rtx_XOR (word_mode, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
/* If we can emit two addi insns then that's better than synthesizing
the constant into a temporary, then adding the temporary to the
ival = INTVAL (operands[2]);
if (TARGET_ZBA
&& (((ival % 2) == 0 && budget1
- > riscv_const_insns (GEN_INT (ival >> 1), true))
+ > riscv_integer_cost (ival >> 1, true))
|| ((ival % 4) == 0 && budget1
- > riscv_const_insns (GEN_INT (ival >> 2), true))
+ > riscv_integer_cost (ival >> 2, true))
|| ((ival % 8) == 0 && budget1
- > riscv_const_insns (GEN_INT (ival >> 3), true))))
+ > riscv_integer_cost (ival >> 3, true))))
{
// Load the shifted constant into a temporary
int shct = ctz_hwi (ival);
return true;
}
+ /* If the constant has the upper 32 bits clear and if after sign
+ extension from 32 to 64 bits it's synthesizable cheaply,
+ then synthesize C' and use add.uw. */
+ if ((TARGET_64BIT && TARGET_ZBA)
+ && (ival & HOST_WIDE_INT_UC (0xffffffff00000000)) == 0
+ && riscv_integer_cost (sext_hwi (ival, 32), true) < budget1)
+ {
+ /* Load the sign extended constant into a temporary. */
+ rtx tempreg = force_reg (word_mode, GEN_INT (sext_hwi (ival, 32)));
+
+ /* Add the zero-extended temporary to the other input to construct
+ the add.uw insn. */
+ rtx x = gen_rtx_ZERO_EXTEND (word_mode, gen_lowpart (SImode, tempreg));
+ x = gen_rtx_PLUS (word_mode, x, operands[1]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
/* If the negated constant is cheaper than the original, then negate
the constant and use sub. */
if (budget2 < budget1)
return false;
HOST_WIDE_INT ival = INTVAL (operands[2]);
- int budget1 = riscv_const_insns (operands[2], true);
- int budget2 = riscv_const_insns (GEN_INT (-INTVAL (operands[2])), true);
+ int budget1 = riscv_integer_cost (INTVAL (operands[2]), true);
+ int budget2 = riscv_integer_cost (-UINTVAL (operands[2]), true);
/* If operands[2] can be split into two 12-bit signed immediates,
split add into two adds. */