Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 229973) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -31850,6 +31850,9 @@ rs6000_rtx_costs (rtx x, machine_mode mo return false; case CTZ: + *total = COSTS_N_INSNS (TARGET_CTZ ? 1 : 4); + return false; + case FFS: *total = COSTS_N_INSNS (4); return false; Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 229972) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -565,6 +565,7 @@ extern int rs6000_vector_align[]; #define TARGET_FCFIDUS TARGET_POPCNTD #define TARGET_FCTIDUZ TARGET_POPCNTD #define TARGET_FCTIWUZ TARGET_POPCNTD +#define TARGET_CTZ TARGET_MODULO #define TARGET_XSCVDPSPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR) #define TARGET_XSCVSPDPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR) Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 229973) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -2101,12 +2101,25 @@ (define_expand "ctz2" (clobber (reg:GPR CA_REGNO))])] "" { + if (TARGET_CTZ) + { + emit_insn (gen_ctz2_hw (operands[0], operands[1])); + DONE; + } + operands[2] = gen_reg_rtx (mode); operands[3] = gen_reg_rtx (mode); operands[4] = gen_reg_rtx (mode); operands[5] = GEN_INT (GET_MODE_BITSIZE (mode) - 1); }) +(define_insn "ctz2_hw" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (ctz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))] + "TARGET_CTZ" + "cnttz %0,%1" + [(set_attr "type" "cntlz")]) + (define_expand "ffs2" [(set (match_dup 2) (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" ""))) Index: gcc/testsuite/gcc.target/powerpc/ctz-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ctz-1.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ctz-1.c (revision 0) @@ -0,0 +1,14 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */ +/* { dg-options "-mcpu=power9 -O3" } */ + +int i_trailing_zero (int a) { return __builtin_ctz (a); } +int l_trailing_zero (long a) { return __builtin_ctzl (a); } +int ll_trailing_zero (long long a) { return __builtin_ctzll (a); } + +/* { dg-final { scan-assembler "cnttzw " } } */ +/* { dg-final { scan-assembler "cnttzd " } } */ +/* { dg-final { scan-assembler-not "cntlzw " } } */ +/* { dg-final { scan-assembler-not "cntlzd " } } */ Index: gcc/testsuite/gcc.target/powerpc/ctz-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ctz-2.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ctz-2.c (revision 0) @@ -0,0 +1,10 @@ +/* { dg-do compile { target { powerpc*-*-* && ilp32 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */ +/* { dg-options "-mcpu=power9 -O3" } */ + +int i_trailing_zero (int a) { return __builtin_ctz (a); } + +/* { dg-final { scan-assembler "cnttzw " } } */ +/* { dg-final { scan-assembler-not "cntlzw " } } */