/* The cntlzw and cntlzd instructions return 32 and 64 for input of zero. */
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
- ((VALUE) = ((MODE) == SImode ? 32 : 64), 1)
+ ((VALUE) = GET_MODE_BITSIZE (MODE), 2)
/* The CTZ patterns that are implemented in terms of CLZ return -1 for input of
- zero. The hardware instructions added in Power9 return 32 or 64. */
+ zero. The hardware instructions added in Power9 and the sequences using
+ popcount return 32 or 64. */
#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
- ((!TARGET_CTZ) \
- ? ((VALUE) = -1, 1) \
- : ((VALUE) = ((MODE) == SImode ? 32 : 64), 1))
+ (TARGET_CTZ || TARGET_POPCNTD \
+ ? ((VALUE) = GET_MODE_BITSIZE (MODE), 2) \
+ : ((VALUE) = -1, 2))
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
[(set_attr "type" "cntlz")])
(define_expand "ctz<mode>2"
- [(set (match_dup 2)
- (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))
- (set (match_dup 3)
- (and:GPR (match_dup 1)
- (match_dup 2)))
- (set (match_dup 4)
- (clz:GPR (match_dup 3)))
- (parallel [(set (match_operand:GPR 0 "gpc_reg_operand" "")
- (minus:GPR (match_dup 5)
- (match_dup 4)))
- (clobber (reg:GPR CA_REGNO))])]
+ [(set (match_operand:GPR 0 "gpc_reg_operand")
+ (ctz:GPR (match_operand:GPR 1 "gpc_reg_operand")))]
""
{
if (TARGET_CTZ)
DONE;
}
- operands[2] = gen_reg_rtx (<MODE>mode);
- operands[3] = gen_reg_rtx (<MODE>mode);
- operands[4] = gen_reg_rtx (<MODE>mode);
- operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1);
+ rtx tmp1 = gen_reg_rtx (<MODE>mode);
+ rtx tmp2 = gen_reg_rtx (<MODE>mode);
+ rtx tmp3 = gen_reg_rtx (<MODE>mode);
+
+ if (TARGET_POPCNTD)
+ {
+ emit_insn (gen_add<mode>3 (tmp1, operands[1], constm1_rtx));
+ emit_insn (gen_one_cmpl<mode>2 (tmp2, operands[1]));
+ emit_insn (gen_and<mode>3 (tmp3, tmp1, tmp2));
+ emit_insn (gen_popcntd<mode>2 (operands[0], tmp3));
+ }
+ else
+ {
+ emit_insn (gen_neg<mode>2 (tmp1, operands[1]));
+ emit_insn (gen_and<mode>3 (tmp2, operands[1], tmp1));
+ emit_insn (gen_clz<mode>2 (tmp3, tmp2));
+ emit_insn (gen_sub<mode>3 (operands[0], GEN_INT (<bits> - 1), tmp3));
+ }
+
+ DONE;
})
(define_insn "ctz<mode>2_hw"
[(set_attr "type" "cntlz")])
(define_expand "ffs<mode>2"
- [(set (match_dup 2)
- (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))
- (set (match_dup 3)
- (and:GPR (match_dup 1)
- (match_dup 2)))
- (set (match_dup 4)
- (clz:GPR (match_dup 3)))
- (parallel [(set (match_operand:GPR 0 "gpc_reg_operand" "")
- (minus:GPR (match_dup 5)
- (match_dup 4)))
- (clobber (reg:GPR CA_REGNO))])]
+ [(set (match_operand:GPR 0 "gpc_reg_operand")
+ (ffs:GPR (match_operand:GPR 1 "gpc_reg_operand")))]
""
{
- operands[2] = gen_reg_rtx (<MODE>mode);
- operands[3] = gen_reg_rtx (<MODE>mode);
- operands[4] = gen_reg_rtx (<MODE>mode);
- operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));
+ rtx tmp1 = gen_reg_rtx (<MODE>mode);
+ rtx tmp2 = gen_reg_rtx (<MODE>mode);
+ rtx tmp3 = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_neg<mode>2 (tmp1, operands[1]));
+ emit_insn (gen_and<mode>3 (tmp2, operands[1], tmp1));
+ emit_insn (gen_clz<mode>2 (tmp3, tmp2));
+ emit_insn (gen_sub<mode>3 (operands[0], GEN_INT (<bits>), tmp3));
+ DONE;
})