diff options
author | Michael Meissner <meissner@gcc.gnu.org> | 2016-06-28 00:01:13 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 2016-06-28 00:01:13 +0000 |
commit | ac11b8c076c6dbce57adae4bca7fd8223bb8936c (patch) | |
tree | b3c57ec34df767be5e78bdc7217001bad31bdeeb /gcc | |
parent | dc448fa03b361f130e7b4554d5e0e5d52e06c891 (diff) | |
download | gcc-ac11b8c076c6dbce57adae4bca7fd8223bb8936c.zip gcc-ac11b8c076c6dbce57adae4bca7fd8223bb8936c.tar.gz gcc-ac11b8c076c6dbce57adae4bca7fd8223bb8936c.tar.bz2 |
vsx.md (UNSPEC_P9_MEMORY): New unspec to support loading and storing byte/half-word values in the vector...
[gcc]
2016-06-27 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/vsx.md (UNSPEC_P9_MEMORY): New unspec to support
loading and storing byte/half-word values in the vector registers.
(vsx_sign_extend_hi_<mode>): Enable the generator function.
(p9_lxsi<wd>zx): New insns to load zero-extended bytes and
half-words on ISA 3.0 to the vector registers.
(p9_stxsi<wd>zx): New insns to store zero-extended bytes and
half-words on ISA 3.0 from the vector registers.
* config/rs6000/rs6000.md (FP_ISA3): New iterator to optimize
converting char/half-word items to floating point on ISA 3.0.
(float<QHI:mode><FP_ISA3:mode>2): On ISA 3.0 generate the lxsihzx
and lxsibzx instructions if we are converting an 8-bit or 16-bit
item from memory to floating point.
(float<QHI:mode><FP_ISA3:mode>2_internal): Likewise.
(floatuns<QHI:mode><FP_ISA3:mode>2): Likewise.
(floatuns<QHI:mode><FP_ISA3:mode>2_internal): Likewise.
(fix_trunc<SFDF:mode><QHI:mode>2): On ISA 3.0 generate the stxsihx
and stxsibx instructions to store floating point values converted
to 8 or 16-bit integers.
(fixuns_trunc<mode>si2): Likewise.
[gcc/testsuite]
2016-06-27 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/p9-fpcvt-1.c: New test to test ISA 3.0 load
byte/half-word to vector registers and store byte/half-word from
vector register instructions.
* gcc.target/powerpc/p9-fpcvt-2.c: Likewise.
From-SVN: r237806
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 141 | ||||
-rw-r--r-- | gcc/config/rs6000/vsx.md | 24 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/p9-fpcvt-1.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/p9-fpcvt-2.c | 19 |
4 files changed, 200 insertions, 1 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 5a5635a..9a39079 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -506,6 +506,12 @@ (IF "TARGET_FLOAT128") (TF "TARGET_LONG_DOUBLE_128")]) +; Iterator for ISA 3.0 supported floating point types +(define_mode_iterator FP_ISA3 [SF + DF + (KF "FLOAT128_IEEE_P (KFmode)") + (TF "FLOAT128_IEEE_P (TFmode)")]) + ; SF/DF suffix for traditional floating instructions (define_mode_attr Ftrad [(SF "s") (DF "")]) @@ -5188,6 +5194,107 @@ [(set_attr "length" "20") (set_attr "type" "fp")]) +;; ISA 3.0 adds instructions lxsi[bh]zx to directly load QImode and HImode to +;; vector registers. At the moment, QI/HImode are not allowed in floating +;; point or vector registers, so we use UNSPEC's to use the load byte and +;; half-word instructions. + +(define_expand "float<QHI:mode><FP_ISA3:mode>2" + [(parallel [(set (match_operand:FP_ISA3 0 "vsx_register_operand") + (float:FP_ISA3 + (match_operand:QHI 1 "input_operand"))) + (clobber (match_scratch:DI 2)) + (clobber (match_scratch:DI 3))])] + "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64" +{ + if (MEM_P (operands[1])) + operands[1] = rs6000_address_for_fpconvert (operands[1]); +}) + +(define_insn_and_split "*float<QHI:mode><FP_ISA3:mode>2_internal" + [(set (match_operand:FP_ISA3 0 "vsx_register_operand" "=<Fv>,<Fv>") + (float:FP_ISA3 + (match_operand:QHI 1 "reg_or_indexed_operand" "r,Z"))) + (clobber (match_scratch:DI 2 "=wi,v")) + (clobber (match_scratch:DI 3 "=r,X"))] + "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64 + && TARGET_UPPER_REGS_DI" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx result = operands[0]; + rtx input = operands[1]; + rtx di = operands[2]; + + if (!MEM_P (input)) + { + rtx tmp = operands[3]; + emit_insn (gen_extend<QHI:mode>di2 (tmp, input)); + emit_move_insn (di, tmp); + } + else + { + machine_mode vmode; + rtx di_vector; + + emit_insn (gen_p9_lxsi<QHI:wd>zx (di, input)); + + if (<MODE>mode == QImode) + vmode = V16QImode; + else if (<MODE>mode == HImode) + vmode = V8HImode; + else + gcc_unreachable (); + + di_vector = gen_rtx_REG (vmode, REGNO (di)); + emit_insn (gen_vsx_sign_extend_<QHI:mode>_di (di, di_vector)); + } + + emit_insn (gen_floatdi<FP_ISA3:mode>2 (result, di)); + DONE; +}) + +(define_expand "floatuns<QHI:mode><FP_ISA3:mode>2" + [(parallel [(set (match_operand:FP_ISA3 0 "vsx_register_operand" "") + (unsigned_float:FP_ISA3 + (match_operand:QHI 1 "input_operand" ""))) + (clobber (match_scratch:DI 2 "")) + (clobber (match_scratch:DI 3 ""))])] + "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64" +{ + if (MEM_P (operands[1])) + operands[1] = rs6000_address_for_fpconvert (operands[1]); +}) + +(define_insn_and_split "*floatuns<QHI:mode><FP_ISA3:mode>2_internal" + [(set (match_operand:FP_ISA3 0 "vsx_register_operand" "=<Fv>,<Fv>") + (unsigned_float:FP_ISA3 + (match_operand:QHI 1 "reg_or_indexed_operand" "r,Z"))) + (clobber (match_scratch:DI 2 "=wi,wi")) + (clobber (match_scratch:DI 3 "=r,X"))] + "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx result = operands[0]; + rtx input = operands[1]; + rtx di = operands[2]; + rtx tmp = operands[3]; + + if (!MEM_P (input)) + { + emit_insn (gen_zero_extend<QHI:mode>di2 (tmp, input)); + emit_move_insn (di, tmp); + } + else + emit_insn (gen_p9_lxsi<QHI:wd>zx (di, input)); + + emit_insn (gen_floatdi<FP_ISA3:mode>2 (result, di)); + DONE; +}) + (define_expand "fix_trunc<mode>si2" [(set (match_operand:SI 0 "gpc_reg_operand" "") (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))] @@ -5296,6 +5403,23 @@ xscvdpsxds %x0,%x1" [(set_attr "type" "fp")]) +(define_expand "fix_trunc<SFDF:mode><QHI:mode>2" + [(use (match_operand:QHI 0 "rs6000_nonimmediate_operand" "")) + (use (match_operand:SFDF 1 "vsx_register_operand" ""))] + "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64" +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx di_tmp = gen_reg_rtx (DImode); + + if (MEM_P (op0)) + op0 = rs6000_address_for_fpconvert (op0); + + emit_insn (gen_fctiwz_<SFDF:mode> (di_tmp, op1)); + emit_insn (gen_p9_stxsi<QHI:wd>x (op0, di_tmp)); + DONE; +}) + (define_expand "fixuns_trunc<mode>si2" [(set (match_operand:SI 0 "gpc_reg_operand" "") (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))] @@ -5368,6 +5492,23 @@ xscvdpuxds %x0,%x1" [(set_attr "type" "fp")]) +(define_expand "fixuns_trunc<SFDF:mode><QHI:mode>2" + [(use (match_operand:QHI 0 "rs6000_nonimmediate_operand" "")) + (use (match_operand:SFDF 1 "vsx_register_operand" ""))] + "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64" +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx di_tmp = gen_reg_rtx (DImode); + + if (MEM_P (op0)) + op0 = rs6000_address_for_fpconvert (op0); + + emit_insn (gen_fctiwuz_<SFDF:mode> (di_tmp, op1)); + emit_insn (gen_p9_stxsi<QHI:wd>x (op0, di_tmp)); + DONE; +}) + ; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ)) ; rather than (set (subreg:SI (reg)) (fix:SI ...)) ; because the first makes it clear that operand 0 is not live diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index a07d66e..b53655f 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -293,6 +293,7 @@ UNSPEC_VSX_XVCVDPSXDS UNSPEC_VSX_XVCVDPUXDS UNSPEC_VSX_SIGN_EXTEND + UNSPEC_P9_MEMORY ]) ;; VSX moves @@ -2705,7 +2706,7 @@ "vextsb2<wd> %0,%1" [(set_attr "type" "vecsimple")]) -(define_insn "*vsx_sign_extend_hi_<mode>" +(define_insn "vsx_sign_extend_hi_<mode>" [(set (match_operand:VSINT_84 0 "vsx_register_operand" "=v") (unspec:VSINT_84 [(match_operand:V8HI 1 "vsx_register_operand" "v")] @@ -2721,3 +2722,24 @@ "TARGET_P9_VECTOR" "vextsw2d %0,%1" [(set_attr "type" "vecsimple")]) + + +;; ISA 3.0 memory operations +(define_insn "p9_lxsi<wd>zx" + [(set (match_operand:DI 0 "vsx_register_operand" "=wi") + (unspec:DI [(zero_extend:DI + (match_operand:QHI 1 "indexed_or_indirect_operand" "Z"))] + UNSPEC_P9_MEMORY))] + "TARGET_P9_VECTOR" + "lxsi<wd>zx %x0,%y1" + [(set_attr "type" "fpload")]) + +(define_insn "p9_stxsi<wd>x" + [(set (match_operand:QHI 0 "reg_or_indexed_operand" "=r,Z") + (unspec:QHI [(match_operand:DI 1 "vsx_register_operand" "wi,wi")] + UNSPEC_P9_MEMORY))] + "TARGET_P9_VECTOR" + "@ + mfvsrd %0,%x1 + stxsi<wd>x %x1,%y0" + [(set_attr "type" "mffgpr,fpstore")]) diff --git a/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-1.c b/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-1.c new file mode 100644 index 0000000..3147492 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mcpu=power9 -O2" } */ + +void sc (signed char *p, double x) { *p = x; } +void uc (unsigned char *p, double x) { *p = x; } +void ss (signed short *p, double x) { *p = x; } +void us (unsigned short *p, double x) { *p = x; } + +/* { dg-final { scan-assembler "stxsibx" } } */ +/* { dg-final { scan-assembler "stxsihx" } } */ +/* { dg-final { scan-assembler-not "mfvsrd" } } */ +/* { dg-final { scan-assembler-not "mfvsrwz" } } */ +/* { dg-final { scan-assembler-not "mtvsrd" } } */ +/* { dg-final { scan-assembler-not "mtvsrwa" } } */ +/* { dg-final { scan-assembler-not "mtvsrwz" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-2.c b/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-2.c new file mode 100644 index 0000000..2d615f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/p9-fpcvt-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mcpu=power9 -O2" } */ + +double sc (signed char *p) { return (double)*p; } +double uc (unsigned char *p) { return (double)*p; } +double ss (signed short *p) { return (double)*p; } +double us (unsigned short *p) { return (double)*p; } + +/* { dg-final { scan-assembler "lxsibzx" } } */ +/* { dg-final { scan-assembler "lxsihzx" } } */ +/* { dg-final { scan-assembler "vextsb2d" } } */ +/* { dg-final { scan-assembler "vextsh2d" } } */ +/* { dg-final { scan-assembler-not "mfvsrd" } } */ +/* { dg-final { scan-assembler-not "mfvsrwz" } } */ +/* { dg-final { scan-assembler-not "mtvsrd" } } */ +/* { dg-final { scan-assembler-not "mtvsrwa" } } */ +/* { dg-final { scan-assembler-not "mtvsrwz" } } */ |