- assert(ia32_mode_needs_gp_reg(mode));
- if (get_mode_size_bits(mode) >= 32)
- return true;
-
- if (is_Proj(transformed_node))
- return upper_bits_clean(get_Proj_pred(transformed_node), mode);
-
- switch (get_ia32_irn_opcode(transformed_node)) {
- case iro_ia32_Conv_I2I:
- case iro_ia32_Conv_I2I8Bit: {
- ir_mode *smaller_mode = get_ia32_ls_mode(transformed_node);
- if (mode_is_signed(smaller_mode) != mode_is_signed(mode))
- return false;
- if (get_mode_size_bits(smaller_mode) > get_mode_size_bits(mode))
- return false;
-
- return true;
- }
-
- case iro_ia32_Shr:
- if (mode_is_signed(mode)) {
- return false; /* TODO handle signed modes */
- } else {
- ir_node *right = get_irn_n(transformed_node, n_ia32_Shr_count);
- if (is_ia32_Immediate(right) || is_ia32_Const(right)) {
- const ia32_immediate_attr_t *attr
- = get_ia32_immediate_attr_const(right);
- if (attr->symconst == 0 &&
- (unsigned)attr->offset >= 32 - get_mode_size_bits(mode)) {
- return true;
- }
- }
- return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Shr_val), mode);
- }
-
- case iro_ia32_Sar:
- /* TODO too conservative if shift amount is constant */
- return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Sar_val), mode);
-
- case iro_ia32_And:
- if (!mode_is_signed(mode)) {
- return
- upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_right), mode) ||
- upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_left), mode);
- }
- /* TODO if one is known to be zero extended, then || is sufficient */
- /* FALLTHROUGH */
- case iro_ia32_Or:
- case iro_ia32_Xor:
- return
- upper_bits_clean(get_irn_n(transformed_node, n_ia32_binary_right), mode) &&
- upper_bits_clean(get_irn_n(transformed_node, n_ia32_binary_left), mode);
-
- case iro_ia32_Const:
- case iro_ia32_Immediate: {
- const ia32_immediate_attr_t *attr =
- get_ia32_immediate_attr_const(transformed_node);
- if (mode_is_signed(mode)) {
- long shifted = attr->offset >> (get_mode_size_bits(mode) - 1);
- return shifted == 0 || shifted == -1;
- } else {
- unsigned long shifted = (unsigned long)attr->offset;
- shifted >>= get_mode_size_bits(mode)-1;
- shifted >>= 1;
- return shifted == 0;
- }
- }
-
- default:
- return false;