@@ -572,6 +572,9 @@ general_scalar_chain::compute_convert_gain ()
{
if (INTVAL (XEXP (src, 1)) >= 32)
igain += ix86_cost->add;
+ /* Gain for extend highpart case. */
+ else if (GET_CODE (XEXP (src, 0)) == ASHIFT)
+ igain += ix86_cost->shift_const - ix86_cost->sse_op;
else
igain += ix86_cost->shift_const;
}
@@ -951,7 +954,8 @@ general_scalar_chain::convert_op (rtx *op, rtx_insn *insn)
{
*op = copy_rtx_if_shared (*op);
- if (GET_CODE (*op) == NOT)
+ if (GET_CODE (*op) == NOT
+ || GET_CODE (*op) == ASHIFT)
{
convert_op (&XEXP (*op, 0), insn);
PUT_MODE (*op, vmode);
@@ -2120,7 +2124,7 @@ general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode)
switch (GET_CODE (src))
{
case ASHIFTRT:
- if (!TARGET_AVX512VL)
+ if (mode == DImode && !TARGET_AVX512VL)
return false;
/* FALLTHRU */
@@ -2131,6 +2135,14 @@ general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode)
if (!CONST_INT_P (XEXP (src, 1))
|| !IN_RANGE (INTVAL (XEXP (src, 1)), 0, GET_MODE_BITSIZE (mode)-1))
return false;
+
+ /* Check for extend highpart case. */
+ if (mode != DImode
+ || GET_CODE (src) != ASHIFTRT
+ || GET_CODE (XEXP (src, 0)) != ASHIFT)
+ break;
+
+ src = XEXP (src, 0);
break;
case SMAX:
@@ -15292,6 +15292,41 @@ (define_insn "*<insn>qi_ext<mode>_2"
(const_string "0")
(const_string "*")))
(set_attr "mode" "QI")])
+
+(define_insn_and_split "*extend<dwi>2_doubleword_highpart"
+ [(set (match_operand:<DWI> 0 "register_operand" "=r")
+ (ashiftrt:<DWI>
+ (ashift:<DWI> (match_operand:<DWI> 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_int_operand"))
+ (match_operand:QI 3 "const_int_operand")))
+ (clobber (reg:CC FLAGS_REG))]
+ "INTVAL (operands[2]) == INTVAL (operands[3])
+ && UINTVAL (operands[2]) < <MODE_SIZE> * BITS_PER_UNIT"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (match_dup 4)
+ (ashift:DWIH (match_dup 4) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel [(set (match_dup 4)
+ (ashiftrt:DWIH (match_dup 4) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_double_mode (<DWI>mode, &operands[0], 1, &operands[0], &operands[4]);")
+
+(define_insn_and_split "*extendv2di2_highpart_stv"
+ [(set (match_operand:V2DI 0 "register_operand" "=v")
+ (ashiftrt:V2DI
+ (ashift:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "vm")
+ (match_operand:QI 2 "const_int_operand"))
+ (match_operand:QI 3 "const_int_operand")))]
+ "!TARGET_64BIT && TARGET_STV && TARGET_AVX512VL
+ && INTVAL (operands[2]) == INTVAL (operands[3])
+ && UINTVAL (operands[2]) < 32"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (ashift:V2DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (ashiftrt:V2DI (match_dup 0) (match_dup 2)))])
;; Rotate instructions
new file mode 100644
@@ -0,0 +1,21 @@
+/* PR target/110717 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#ifdef __SIZEOF_INT128__
+unsigned __int128
+foo (unsigned __int128 x)
+{
+ x <<= 59;
+ return ((__int128) x) >> 59;
+}
+#else
+unsigned long long
+foo (unsigned long long x)
+{
+ x <<= 27;
+ return ((long long) x) >> 27;
+}
+#endif
+
+/* { dg-final { scan-assembler-not "sh\[lr\]d" } } */