Hi, I experienced an issue in our port, which I suspected due to bugs in ptr_difference_const & split_address_to_core_and_offset. Basically, ptr_difference_const, called by ivopts pass, tries to evaluate whether e1 & e2 differ by a const. In this example,
e1 is (addr_expr (mem_ref (ssa_name1, 8)) e2 is just ssa_name1. It is obvious to me that ptr_difference_const should return true. But it calls split_address_to_core_and_offset to split e1 to some base pointer and offset. split_addess_to_core_and_offset in turn calls get_inner_reference to do it. get_inner_reference cannot handle (mem_ref (ssa_name1, 8)), it just returns the same expression back. get_inner_reference function case MEM_REF: /* Hand back the decl for MEM[&decl, off]. */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR) { tree off = TREE_OPERAND (exp, 1); if (!integer_zerop (off)) { double_int boff, coff = mem_ref_offset (exp); boff = coff.alshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT), HOST_BITS_PER_DOUBLE_INT); bit_offset += boff; } exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); } goto done; Then in ptr_difference_const, we get core1 as (mem_ref (ssa_name1, 8)) and toffset1 is empty. ptr_difference_const will return false as result. There is another possible bug in ptr_difference_const. If one of toffset1 & toffset2 is true, why it returns false? The comment doesn't make sense to me. In this example, toffset1 should be 8 and toffset2 should be empty. No way it should return false. else if (toffset1 || toffset2) { /* If only one of the offsets is non-constant, the difference cannot be a constant. */ return false; } Any comment? I would like to submit a patch for it. The problem is I don't have an reproducible example on x86 or other public targets. I ran through the x86-64 tests and didn't hit a single case that meets this condition. e1 is (addr_expr (mem_ref (ssa_name1, 8)) e2 is just ssa_name1. Not sure about other targets though. Thanks, Bingfeng