Ping: [PATCH] rs6000: powerpc suboptimal boolean test of contiguous bits [PR102239]
Ping, thanks. On 2021/12/13 13:16, Xionghu Luo wrote: > Add specialized version to combine two instructions from > > 9: {r123:CC=cmp(r124:DI&0x6,0);clobber scratch;} >REG_DEAD r124:DI > 10: pc={(r123:CC==0)?L15:pc} > REG_DEAD r123:CC > > to: > > 10: {pc={(r123:DI&0x6==0)?L15:pc};clobber scratch;clobber %0:CC;} > > then split2 will split it to one rotate dot instruction (to save one > rotate back instruction) as shifted result doesn't matter when comparing > to 0 in CCEQmode. > > Bootstrapped and regression tested pass on Power 8/9/10, OK for master? > > gcc/ChangeLog: > > PR target/102239 > * config/rs6000/rs6000.md (*anddi3_insn_dot): New. > > gcc/testsuite/ChangeLog: > > PR target/102239 > * gcc.target/powerpc/pr102239.c: New test. > --- > gcc/config/rs6000/rs6000-protos.h | 1 + > gcc/config/rs6000/rs6000.c | 7 > gcc/config/rs6000/rs6000.md | 38 + > gcc/testsuite/gcc.target/powerpc/pr102239.c | 13 +++ > 4 files changed, 59 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/powerpc/pr102239.c > > diff --git a/gcc/config/rs6000/rs6000-protos.h > b/gcc/config/rs6000/rs6000-protos.h > index 14f6b313105..3644c524376 100644 > --- a/gcc/config/rs6000/rs6000-protos.h > +++ b/gcc/config/rs6000/rs6000-protos.h > @@ -73,6 +73,7 @@ extern int expand_block_move (rtx[], bool); > extern bool expand_block_compare (rtx[]); > extern bool expand_strn_compare (rtx[], int); > extern bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode); > +extern bool rs6000_is_valid_rotate_dot_mask (rtx mask, machine_mode mode); > extern bool rs6000_is_valid_and_mask (rtx, machine_mode); > extern bool rs6000_is_valid_shift_mask (rtx, rtx, machine_mode); > extern bool rs6000_is_valid_insert_mask (rtx, rtx, machine_mode); > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c > index 5e129986516..57a38cf954a 100644 > --- a/gcc/config/rs6000/rs6000.c > +++ b/gcc/config/rs6000/rs6000.c > @@ -11606,6 +11606,13 @@ rs6000_is_valid_mask (rtx mask, int *b, int *e, > machine_mode mode) >return true; > } > > +bool > +rs6000_is_valid_rotate_dot_mask (rtx mask, machine_mode mode) > +{ > + int nb, ne; > + return rs6000_is_valid_mask (mask, &nb, &ne, mode) && nb >= ne && ne > 0; > +} > + > /* Return whether MASK (a CONST_INT) is a valid mask for any rlwinm, rldicl, > or rldicr instruction, to implement an AND with it in mode MODE. */ > > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index 6bec2bddbde..014dc9612ea 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -3762,6 +3762,44 @@ (define_insn_and_split "*and3_2insn_dot2" > (set_attr "dot" "yes") > (set_attr "length" "8,12")]) > > +(define_insn_and_split "*anddi3_insn_dot" > + [(set (pc) > +(if_then_else (eq (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r") > + (match_operand:DI 2 "const_int_operand" "n,n")) > + (const_int 0)) > + (label_ref (match_operand 3 "")) > + (pc))) > + (clobber (match_scratch:DI 0 "=r,r")) > + (clobber (reg:CC CR0_REGNO))] > + "rs6000_is_valid_rotate_dot_mask (operands[2], DImode) > + && TARGET_POWERPC64" > + "#" > + "&& reload_completed" > + [(pc)] > +{ > + int nb, ne; > + if (rs6000_is_valid_mask (operands[2], &nb, &ne, DImode) > + && nb >= ne > + && ne > 0) > + { > + unsigned HOST_WIDE_INT val = INTVAL (operands[2]); > + int shift = 63 - nb; > + rtx tmp = gen_rtx_ASHIFT (DImode, operands[1], GEN_INT (shift)); > + tmp = gen_rtx_AND (DImode, tmp, GEN_INT (val << shift)); > + rtx cr0 = gen_rtx_REG (CCmode, CR0_REGNO); > + rs6000_emit_dot_insn (operands[0], tmp, 1, cr0); > + rtx loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); > + rtx cond = gen_rtx_EQ (CCEQmode, cr0, const0_rtx); > + rtx ite = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, loc_ref, pc_rtx); > + emit_jump_insn (gen_rtx_SET (pc_rtx, ite)); > + DONE; > + } > + else > + FAIL; > +} > + [(set_attr "type" "shift") > + (set_attr "dot" "yes") > + (set_attr "length" "8,12")]) > > (define_expand "3" >[(set (match_operand:SDI 0 "gpc_reg_operand") > diff --git a/gcc/testsuite/gcc.target/powerpc/pr102239.c > b/gcc/testsuite/gcc.target/powerpc/pr102239.c > new file mode 100644 > index 000..1bafc9fe18e > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/pr102239.c > @@ -0,0 +1,13 @@ > +/* { dg-do compile } */ > +/* { dg-require-effective-target lp64 } */ > +/* { dg-options "-O2" } */ > + > +void foo(long arg) > +{ > + if (arg & ((1UL << 33) | (1UL << 34))) > +asm volatile("# if"); > + else > +asm volatile("# else"); > +} > + > +/* { dg-final { scan-assembler-times "rldicr." 1 } } */ -- Thanks, Xionghu
Re: Ping: [PATCH] rs6000: powerpc suboptimal boolean test of contiguous bits [PR102239]
On Mon, Jan 10, 2022 at 12:37 AM Xionghu Luo wrote: > > Ping, thanks. > > > On 2021/12/13 13:16, Xionghu Luo wrote: > > Add specialized version to combine two instructions from > > > > 9: {r123:CC=cmp(r124:DI&0x6,0);clobber scratch;} > >REG_DEAD r124:DI > > 10: pc={(r123:CC==0)?L15:pc} > > REG_DEAD r123:CC > > > > to: > > > > 10: {pc={(r123:DI&0x6==0)?L15:pc};clobber scratch;clobber %0:CC;} > > > > then split2 will split it to one rotate dot instruction (to save one > > rotate back instruction) as shifted result doesn't matter when comparing > > to 0 in CCEQmode. > > > > Bootstrapped and regression tested pass on Power 8/9/10, OK for master? > > > > gcc/ChangeLog: > > > > PR target/102239 > > * config/rs6000/rs6000.md (*anddi3_insn_dot): New. > > > > gcc/testsuite/ChangeLog: > > > > PR target/102239 > > * gcc.target/powerpc/pr102239.c: New test. > > --- > > gcc/config/rs6000/rs6000-protos.h | 1 + > > gcc/config/rs6000/rs6000.c | 7 > > gcc/config/rs6000/rs6000.md | 38 + > > gcc/testsuite/gcc.target/powerpc/pr102239.c | 13 +++ > > 4 files changed, 59 insertions(+) > > create mode 100644 gcc/testsuite/gcc.target/powerpc/pr102239.c > > > > diff --git a/gcc/config/rs6000/rs6000-protos.h > > b/gcc/config/rs6000/rs6000-protos.h > > index 14f6b313105..3644c524376 100644 > > --- a/gcc/config/rs6000/rs6000-protos.h > > +++ b/gcc/config/rs6000/rs6000-protos.h > > @@ -73,6 +73,7 @@ extern int expand_block_move (rtx[], bool); > > extern bool expand_block_compare (rtx[]); > > extern bool expand_strn_compare (rtx[], int); > > extern bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode); > > +extern bool rs6000_is_valid_rotate_dot_mask (rtx mask, machine_mode mode); > > extern bool rs6000_is_valid_and_mask (rtx, machine_mode); > > extern bool rs6000_is_valid_shift_mask (rtx, rtx, machine_mode); > > extern bool rs6000_is_valid_insert_mask (rtx, rtx, machine_mode); > > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c > > index 5e129986516..57a38cf954a 100644 > > --- a/gcc/config/rs6000/rs6000.c > > +++ b/gcc/config/rs6000/rs6000.c > > @@ -11606,6 +11606,13 @@ rs6000_is_valid_mask (rtx mask, int *b, int *e, > > machine_mode mode) > >return true; > > } > > > > +bool > > +rs6000_is_valid_rotate_dot_mask (rtx mask, machine_mode mode) > > +{ > > + int nb, ne; > > + return rs6000_is_valid_mask (mask, &nb, &ne, mode) && nb >= ne && ne > 0; > > +} > > + > > /* Return whether MASK (a CONST_INT) is a valid mask for any rlwinm, > > rldicl, > > or rldicr instruction, to implement an AND with it in mode MODE. */ > > > > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > > index 6bec2bddbde..014dc9612ea 100644 > > --- a/gcc/config/rs6000/rs6000.md > > +++ b/gcc/config/rs6000/rs6000.md > > @@ -3762,6 +3762,44 @@ (define_insn_and_split "*and3_2insn_dot2" > > (set_attr "dot" "yes") > > (set_attr "length" "8,12")]) > > > > +(define_insn_and_split "*anddi3_insn_dot" This pattern needs a name that better represents its purpose. The pattern name implies that it's operating on a combination of AND and Record Condition bit. Also "insn" is confusing; I think that you are using the template from the 2insn_dot names, so this should explicitly be 1insn. Maybe "branch_anddi3_1insn_dot", or just "branch_anddi3_dot". > > + [(set (pc) > > +(if_then_else (eq (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r") > > + (match_operand:DI 2 "const_int_operand" "n,n")) > > + (const_int 0)) > > + (label_ref (match_operand 3 "")) > > + (pc))) > > + (clobber (match_scratch:DI 0 "=r,r")) > > + (clobber (reg:CC CR0_REGNO))] > > + "rs6000_is_valid_rotate_dot_mask (operands[2], DImode) > > + && TARGET_POWERPC64" > > + "#" > > + "&& reload_completed" > > + [(pc)] > > +{ > > + int nb, ne; > > + if (rs6000_is_valid_mask (operands[2], &nb, &ne, DImode) > > + && nb >= ne > > + && ne > 0) > > + { > > + unsigned HOST_WIDE_INT val = INTVAL (operands[2]); > > + int shift = 63 - nb; > > + rtx tmp = gen_rtx_ASHIFT (DImode, operands[1], GEN_INT (shift)); > > + tmp = gen_rtx_AND (DImode, tmp, GEN_INT (val << shift)); > > + rtx cr0 = gen_rtx_REG (CCmode, CR0_REGNO); > > + rs6000_emit_dot_insn (operands[0], tmp, 1, cr0); > > + rtx loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); > > + rtx cond = gen_rtx_EQ (CCEQmode, cr0, const0_rtx); > > + rtx ite = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, loc_ref, pc_rtx); > > + emit_jump_insn (gen_rtx_SET (pc_rtx, ite)); > > + DONE; > > + } > > + else > > + FAIL; > > +} > > + [(set_attr "type" "shift") > > + (set_attr "dot" "yes") > > + (set_attr "length" "8,12")]) > > > > (define_expand "3" > >[(set (match_operand:SDI 0 "gpc_reg_operand") > > diff --git a/gcc/test