+ /* We can optimize some special cases of ZERO_EXTEND. */
+ if (GET_CODE (x) == ZERO_EXTEND)
+ {
+ /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI if we
+ know that the last value didn't have any inappropriate bits
+ set. */
+ if (GET_CODE (XEXP (x, 0)) == TRUNCATE
+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
+ && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+ && (nonzero_bits (XEXP (XEXP (x, 0), 0), GET_MODE (x))
+ & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ return XEXP (XEXP (x, 0), 0);
+
+ /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)). */
+ if (GET_CODE (XEXP (x, 0)) == SUBREG
+ && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
+ && subreg_lowpart_p (XEXP (x, 0))
+ && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+ && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), GET_MODE (x))
+ & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))) == 0)
+ return SUBREG_REG (XEXP (x, 0));
+
+ /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI when foo
+ is a comparison and STORE_FLAG_VALUE permits. This is like
+ the first case, but it works even when GET_MODE (x) is larger
+ than HOST_WIDE_INT. */
+ if (GET_CODE (XEXP (x, 0)) == TRUNCATE
+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
+ && GET_RTX_CLASS (GET_CODE (XEXP (XEXP (x, 0), 0))) == '<'
+ && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && ((HOST_WIDE_INT) STORE_FLAG_VALUE
+ & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ return XEXP (XEXP (x, 0), 0);
+
+ /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)). */
+ if (GET_CODE (XEXP (x, 0)) == SUBREG
+ && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
+ && subreg_lowpart_p (XEXP (x, 0))
+ && GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0)))) == '<'
+ && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && ((HOST_WIDE_INT) STORE_FLAG_VALUE
+ & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ return SUBREG_REG (XEXP (x, 0));
+
+ /* If sign extension is cheaper than zero extension, then use it
+ if we know that no extraneous bits are set, and that the high
+ bit is not set. */
+ if (flag_expensive_optimizations
+ && ((GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+ && ((nonzero_bits (XEXP (x, 0), GET_MODE (x))
+ & ~ (((unsigned HOST_WIDE_INT)
+ GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
+ >> 1))
+ == 0))
+ || (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
+ && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && (((HOST_WIDE_INT) STORE_FLAG_VALUE
+ & ~ (((unsigned HOST_WIDE_INT)
+ GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
+ >> 1))
+ == 0))))
+ {
+ rtx temp = gen_rtx (SIGN_EXTEND, GET_MODE (x), XEXP (x, 0));
+
+ if (rtx_cost (temp, SET) < rtx_cost (x, SET))
+ return expand_compound_operation (temp);
+ }
+ }
+