From: Jiufu Guo Date: Mon, 19 Dec 2022 08:40:01 +0000 (+0800) Subject: rs6000: use li;x?oris to build constant X-Git-Tag: upstream/13.1.0~2473 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=97a8e88cd7d22562c0ea4f73687d3c93c21e12fb;p=platform%2Fupstream%2Fgcc.git rs6000: use li;x?oris to build constant For constant C: If '(c & 0xFFFFFFFF00008000ULL) == 0xFFFFFFFF00008000ULL' or say: 32(1) || 16(x) || 1(1) || 15(x), using "li; xoris" would be ok. If '(c & 0xFFFFFFFF80008000ULL) == 0x80000000ULL' or say: 32(0) || 1(1) || 15(x) || 1(0) || 15(x), we could use "li; oris" to build constant 'C'. Here N(M) means N continuous bit M, x for M means it is ok for either 1 or 0; '||' means concatenation. This patch update rs6000_emit_set_long_const to support those constants. PR target/106708 gcc/ChangeLog: * config/rs6000/rs6000.cc (rs6000_emit_set_long_const): Add using "li; x?oris" to build constant. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr106708.c: New test. --- diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index b3a609f..9318ef1 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -10251,17 +10251,42 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c) if (ud1 != 0) emit_move_insn (dest, gen_rtx_IOR (DImode, temp, GEN_INT (ud1))); } + else if (ud4 == 0xffff && ud3 == 0xffff && (ud1 & 0x8000)) + { + /* li; xoris */ + temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode); + emit_move_insn (temp, GEN_INT (sext_hwi (ud1, 16))); + emit_move_insn (dest, gen_rtx_XOR (DImode, temp, + GEN_INT ((ud2 ^ 0xffff) << 16))); + } else if (ud3 == 0 && ud4 == 0) { temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode); gcc_assert (ud2 & 0x8000); - emit_move_insn (temp, GEN_INT (sext_hwi (ud2 << 16, 32))); - if (ud1 != 0) - emit_move_insn (temp, gen_rtx_IOR (DImode, temp, GEN_INT (ud1))); - emit_move_insn (dest, - gen_rtx_ZERO_EXTEND (DImode, - gen_lowpart (SImode,temp))); + + if (ud1 == 0) + { + /* lis; rldicl */ + emit_move_insn (temp, GEN_INT (sext_hwi (ud2 << 16, 32))); + emit_move_insn (dest, + gen_rtx_AND (DImode, temp, GEN_INT (0xffffffff))); + } + else if (!(ud1 & 0x8000)) + { + /* li; oris */ + emit_move_insn (temp, GEN_INT (ud1)); + emit_move_insn (dest, + gen_rtx_IOR (DImode, temp, GEN_INT (ud2 << 16))); + } + else + { + /* lis; ori; rldicl */ + emit_move_insn (temp, GEN_INT (sext_hwi (ud2 << 16, 32))); + emit_move_insn (temp, gen_rtx_IOR (DImode, temp, GEN_INT (ud1))); + emit_move_insn (dest, + gen_rtx_AND (DImode, temp, GEN_INT (0xffffffff))); + } } else if (ud1 == ud3 && ud2 == ud4) { diff --git a/gcc/testsuite/gcc.target/powerpc/pr106708.c b/gcc/testsuite/gcc.target/powerpc/pr106708.c new file mode 100644 index 0000000..ddb9160 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr106708.c @@ -0,0 +1,41 @@ +/* PR target/106708 */ +/* { dg-do run } */ +/* { dg-options "-O2 -mno-prefixed -save-temps" } */ +/* { dg-require-effective-target has_arch_ppc64 } */ + +long long arr[] + = {0xffffffff7cdeab55LL, 0x98765432LL, 0xabcd0000LL}; + +void __attribute__ ((__noipa__)) test_li_xoris (long long *arg) +{ + *arg = 0xffffffff7cdeab55LL; +} +/* { dg-final { scan-assembler-times {\mli .*,-21675\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxoris .*0x8321\M} 1 } } */ + +void __attribute__ ((__noipa__)) test_li_oris (long long *arg) +{ + *arg = 0x98765432LL; +} +/* { dg-final { scan-assembler-times {\mli .*,21554\M} 1 } } */ +/* { dg-final { scan-assembler-times {\moris .*0x9876\M} 1 } } */ + +void __attribute__ ((__noipa__)) test_lis_rldicl (long long *arg) +{ + *arg = 0xabcd0000LL; +} +/* { dg-final { scan-assembler-times {\mlis .*,0xabcd\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mrldicl .*,0,32\M} 1 } } */ + +int +main () +{ + long long a[sizeof (arr) / sizeof (arr[0])]; + + test_li_xoris (a); + test_li_oris (a + 1); + test_lis_rldicl (a + 2); + if (__builtin_memcmp (a, arr, sizeof (arr)) != 0) + __builtin_abort (); + return 0; +}