aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorCong Hou <congh@google.com>2013-10-30 16:01:47 -0400
committerCong Hou <congh@gcc.gnu.org>2013-10-30 16:01:47 -0400
commit8f24613d021f267f24d39f51b5423c308060b42c (patch)
tree4d5c5a0a6bd64a5d027d233c09decc80c1aef2b4 /gcc/config
parentafbb631e67b011f5d68dabf3f42bfca846f27fc1 (diff)
downloadgcc-8f24613d021f267f24d39f51b5423c308060b42c.zip
gcc-8f24613d021f267f24d39f51b5423c308060b42c.tar.gz
gcc-8f24613d021f267f24d39f51b5423c308060b42c.tar.bz2
re PR target/58762 ([missed optimization] Vectorizing abs(int).)
2013-10-30 Cong Hou <congh@google.com> PR target/58762 * config/i386/i386-protos.h (ix86_expand_sse2_abs): New function. * config/i386/i386.c (ix86_expand_sse2_abs): New function. * config/i386/sse.md: Add SSE2 support to abs (8/16/32-bit-int). 2013-10-30 Cong Hou <congh@google.com> * gcc.target/i386/vect-abs-s8.c: New test. * gcc.target/i386/vect-abs-s16.c: New test. * gcc.target/i386/vect-abs-s32.c: New test. From-SVN: r204229
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c47
-rw-r--r--gcc/config/i386/sse.md15
3 files changed, 62 insertions, 1 deletions
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index b1d014a..5799251 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -240,6 +240,7 @@ extern void ix86_expand_mul_widen_evenodd (rtx, rtx, rtx, bool, bool);
extern void ix86_expand_mul_widen_hilo (rtx, rtx, rtx, bool, bool);
extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx);
extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx);
+extern void ix86_expand_sse2_abs (rtx, rtx);
extern bool ix86_bnd_prefixed_insn_p (rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 93a8b28..3131efd 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -42020,6 +42020,53 @@ ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED)
return false;
}
+void
+ix86_expand_sse2_abs (rtx op0, rtx op1)
+{
+ enum machine_mode mode = GET_MODE (op0);
+ rtx tmp0, tmp1;
+
+ switch (mode)
+ {
+ /* For 32-bit signed integer X, the best way to calculate the absolute
+ value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
+ case V4SImode:
+ tmp0 = expand_simple_binop (mode, ASHIFTRT, op1,
+ GEN_INT (GET_MODE_BITSIZE
+ (GET_MODE_INNER (mode)) - 1),
+ NULL, 0, OPTAB_DIRECT);
+ if (tmp0)
+ tmp1 = expand_simple_binop (mode, XOR, op1, tmp0,
+ NULL, 0, OPTAB_DIRECT);
+ if (tmp0 && tmp1)
+ expand_simple_binop (mode, MINUS, tmp1, tmp0,
+ op0, 0, OPTAB_DIRECT);
+ break;
+
+ /* For 16-bit signed integer X, the best way to calculate the absolute
+ value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
+ case V8HImode:
+ tmp0 = expand_unop (mode, neg_optab, op1, NULL_RTX, 0);
+ if (tmp0)
+ expand_simple_binop (mode, SMAX, op1, tmp0, op0, 0,
+ OPTAB_DIRECT);
+ break;
+
+ /* For 8-bit signed integer X, the best way to calculate the absolute
+ value of X is min ((unsigned char) X, (unsigned char) (-X)),
+ as SSE2 provides the PMINUB insn. */
+ case V16QImode:
+ tmp0 = expand_unop (mode, neg_optab, op1, NULL_RTX, 0);
+ if (tmp0)
+ expand_simple_binop (V16QImode, UMIN, op1, tmp0, op0, 0,
+ OPTAB_DIRECT);
+ break;
+
+ default:
+ break;
+ }
+}
+
/* Expand an insert into a vector register through pinsr insn.
Return true if successful. */
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 041ca64..584a011 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -10270,7 +10270,7 @@
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
-(define_insn "abs<mode>2"
+(define_insn "*abs<mode>2"
[(set (match_operand:VI124_AVX2_48_AVX512F 0 "register_operand" "=v")
(abs:VI124_AVX2_48_AVX512F
(match_operand:VI124_AVX2_48_AVX512F 1 "nonimmediate_operand" "vm")))]
@@ -10282,6 +10282,19 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "abs<mode>2"
+ [(set (match_operand:VI124_AVX2_48_AVX512F 0 "register_operand")
+ (abs:VI124_AVX2_48_AVX512F
+ (match_operand:VI124_AVX2_48_AVX512F 1 "nonimmediate_operand")))]
+ "TARGET_SSE2"
+{
+ if (!TARGET_SSSE3)
+ {
+ ix86_expand_sse2_abs (operands[0], operands[1]);
+ DONE;
+ }
+})
+
(define_insn "abs<mode>2"
[(set (match_operand:MMXMODEI 0 "register_operand" "=y")
(abs:MMXMODEI