}
break;
- case ASHIFT:
case SS_ASHIFT:
+ if (CONST_INT_P (trueop0)
+ && HWI_COMPUTABLE_MODE_P (mode)
+ && (UINTVAL (trueop0) == (GET_MODE_MASK (mode) >> 1)
+ || mode_signbit_p (mode, trueop0))
+ && ! side_effects_p (op1))
+ return op0;
+ goto simplify_ashift;
+
case US_ASHIFT:
+ if (CONST_INT_P (trueop0)
+ && HWI_COMPUTABLE_MODE_P (mode)
+ && UINTVAL (trueop0) == GET_MODE_MASK (mode)
+ && ! side_effects_p (op1))
+ return op0;
+ /* FALLTHRU */
+
+ case ASHIFT:
+simplify_ashift:
if (trueop1 == CONST0_RTX (mode))
return op0;
if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
case LSHIFTRT:
case ASHIFTRT:
case ASHIFT:
+ case SS_ASHIFT:
+ case US_ASHIFT:
{
wide_int wop1 = pop1;
if (SHIFT_COUNT_TRUNCATED)
result = wi::lshift (pop0, wop1);
break;
+ case SS_ASHIFT:
+ if (wi::leu_p (wop1, wi::clrsb (pop0)))
+ result = wi::lshift (pop0, wop1);
+ else if (wi::neg_p (pop0))
+ result = wi::min_value (int_mode, SIGNED);
+ else
+ result = wi::max_value (int_mode, SIGNED);
+ break;
+
+ case US_ASHIFT:
+ if (wi::eq_p (pop0, 0))
+ result = pop0;
+ else if (wi::leu_p (wop1, wi::clz (pop0)))
+ result = wi::lshift (pop0, wop1);
+ else
+ result = wi::max_value (int_mode, UNSIGNED);
+ break;
+
default:
gcc_unreachable ();
}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int test_ok_pos()
+{
+ int x = 100;
+ return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+int test_ok_neg()
+{
+ int x = -100;
+ return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+int test_sat_max()
+{
+ int x = 10000;
+ return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+int test_sat_min()
+{
+ int x = -10000;
+ return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+short stest_ok_pos()
+{
+ short x = 100;
+ return __builtin_bfin_shl_fr1x16(x,8);
+}
+
+short stest_ok_neg()
+{
+ short x = -100;
+ return __builtin_bfin_shl_fr1x16(x,8);
+}
+
+short stest_sat_max()
+{
+ short x = 10000;
+ return __builtin_bfin_shl_fr1x16(x,8);
+}
+
+short stest_sat_min()
+{
+ short x = -10000;
+ return __builtin_bfin_shl_fr1x16(x,8);
+}
+/* { dg-final { scan-assembler-not "\\(S\\)" } } */
+/* { dg-final { scan-assembler-not "\\(V,S\\)" } } */