> On Mon, 29 Jun 2026, Filip Kastl wrote:
> > Ah and one more detail: I'm working with all constraints involving uses and
> > clobbers disabled (I don't call
> > gimple-ssa-pta-constraints.cc:find_func_clobbers). I'm mentioning that in
> > case
> > you'd be confused that some constraints are missing.
> >
> > But the mystery of why Andersen decides to fill those sets remains.
> >
> > Filip
> >
> > On Mon 2026-06-29 11:57:49, Filip Kastl wrote:
> > > Hi Richi,
> > >
> > > I have another question about PTA that may or may not be related to the
> > > last
> > > week's question.
> > >
> > > I'm debugging a difference between what my Steensgaard-style solver and
> > > what
> > > GCC's Andersen-style solver compute. In particular on my testcase (gcc_r
> > > from
> > > 2017 SPEC CPU) Steensgaard computes these sets...
> > >
> > > ix86_encode_section_info.clobber = { }
> > > ix86_encode_section_info.use = { }
> > > ix86_encode_section_info.result = { }
> > > ix86_encode_section_info.arg0 = { NULL ANYTHING STRING ESCAPED N ...
> > > ix86_encode_section_info.arg1 = { NULL ANYTHING STRING ESCAPED N ...
> > > ix86_encode_section_info.arg2 = { }
> > >
> > > ...while Steensgaard computes this:
> > >
> > > ix86_encode_section_info.clobber = { NULL ANYTHING p p }
> > > ix86_encode_section_info.use = { NULL ANYTHING p p }
> > > ix86_encode_section_info.result = { NULL ANYTHING p p }
> > > ix86_encode_section_info.arg0 = { NULL ANYTHING p p }
> > > ix86_encode_section_info.arg1 = { NULL ANYTHING p p }
> > > ix86_encode_section_info.arg2 = { NULL ANYTHING p p }
> > >
> > > To figure out how Andersen arrived at these sets I searched the IPA PTA
> > > dump
> > > for constraints involving ix86_encode_section_info*. I found only
> > > these...
>
> It's been some time since I had the Andersen code swapped in my brain,
> so please bear with me eventually giving false hints ...
>
> > > Generating constraints for ix86_encode_section_info/332
> > > (ix86_encode_section_info)
> > > _18 = *ix86_encode_section_info.arg1
> > > _19 = *ix86_encode_section_info.arg1 + 64
> > > _24 = *ix86_encode_section_info.arg0
> > > *_26 + 5 = ix86_encode_section_info.arg0
> > > _30 = *ix86_encode_section_info.arg0
> > > _31 = *ix86_encode_section_info.arg0 + 1165
> > > _32 = *ix86_encode_section_info.arg0 + 1160
> > > *_38 + 5 = ix86_encode_section_info.arg0
> > > _41 = *ix86_encode_section_info.arg0
> > > _44 = *ix86_encode_section_info.arg0 + 472
> > > _46 = *ix86_encode_section_info.arg0 + 24
> > > _1 = *ix86_encode_section_info.arg0
> > > _2 = *ix86_encode_section_info.arg0 + 24
> > > _4 = *ix86_encode_section_info.arg0 + 472
> > > _55 = *ix86_encode_section_info.arg0
> > > _56 = *ix86_encode_section_info.arg0 + 1024
> > > _60 = *ix86_encode_section_info.arg0 + 128
> > > _17 = *ix86_encode_section_info.arg1 + 64
> > >
> > > ...which is strange. I don't see any assigning into
> > > ix86_encode_section_info*
> > > nor assigning &ix86_encode_section_info* into any other set. Shouldn't
> > > then
> > > Andersen compute empty sets for all of these? (Although it is a good
> > > thing
> > > that Andersen fills those sets. Otherwise, there would be a
> > > miscompilation.
> > > I just want to understand what is it that my solver fails to do here.)
>
> There must be call sites of ix86_encode_section_info/332 and I'd expect
> those to have constraints like
>
> ix86_encode_section_info.arg0 = ...
I don't see any constraints like this. But since the function only gets called
indirectly, that makes sense to me.
> &ix86_encode_section_info itself would appear when the function is only
> called indirectly ...
>
> > > First explanation I came up with was expanding of
> > > ix86_encode_section_info (the
> > > fninfo) using '+ UNKNOWN' that we discussed last week. But
> > > ix86_encode_section_info is not present in any constraint at all so it
> > > cannot
> > > be present in any pt set and therefore it cannot get expanded this way.
> > >
> > > Note that ix86_encode_section_info is only ever called indirectly through
> > > a
> > > function pointer targetm.encode_section_info. That may be relevant here,
> > > I
> > > think.
>
> ... as you say here. It might be only visible when creating
> constraints for the targem initializer (a global).
Not sure what you mean by this sentence ^. Could you expand on this a bit?
> We might end up
> with just feeding that from NONLOCAL and thus you'd get ESCAPED
> at uses and ix86_encode_section_info should be escaped?
Hm, doesn't look like ix86_encode_section_info escaped though:
ESCAPED = { NULL ANYTHING STRING ESCAPED NONLOCAL output_object_block_htab
const_desc_eq assemble_real.arg0 mark_constant object_block_entry_hash
gt_pch_p_P23constant_descriptor_rtx4htab gt_pch_p_17rtx_constant_pool
const_rtx_hash_1 section_entry_eq emutls_common_1 const_desc_rtx_eq
section_entry_hash gt_pch_p_23constant_descriptor_rtx compute_reloc_for_rtx_1
const_desc_rtx_hash const_desc_hash object_block_entry_eq
build_int_cst_wide_type.arg1 build_int_cst_wide_type.arg2 type_hash_eq
gt_pch_p_P9type_hash4htab gt_pch_p_9type_hash cl_option_hash_eq
cl_option_hash_hash type_hash_hash tree_map_hash tree_map_base_hash
tree_map_base_eq int_cst_hash_eq int_cst_hash_hash gt_pch_p_17stack_local_entry
ix86_init_machine_status extended_reg_mentioned_1 get_some_local_dynamic_name_1
dconst0 dconsthalf dconstm1 internal_label_prefix optab_table dconst1 isa_other
target_other name name label tmp_label key.0+64 key.0+64 buf buf buffer x reloc
flagchars ggc_calloc ggc_free in.0+64 label tmp.0+64 x h label data body
in.0+64 lhd_dwarf_name gimple_decl_printable_name lhd_set_decl_assembler_name
gimple_fold_obj_type_ref mode_name_buf D.16879.0+64 D.16880.0+64 dc p code code
precision in.0+64 in.0+64 in.0+64 in.0+64 in.0+64 in.0+64 in in p low1 hi
d.0+32 TWO52r.0+32 half_minus_pred_half.0+32 pred_half.0+32 TWO52r.0+32
TWO52r.0+32 TWO52r.0+32 TWO52r.0+32 TWO52r.0+32 TWO52r.0+32
half_minus_pred_half.0+32 pred_half.0+32 r.0+32 inf.0+32 words use r.0+32 dstr
dstr ONE16r.0+32 TWO31r.0+32 r.0+32 l xops xops name r.0+32 cur_target rperm
rperm rperm rperm name xops rperm buf name } same as lookup_constant_def.result
In fact, I don't see ix86_encode_section_info in any PT set in the dump.
> > >
> > > Do you have any hunch about what is going on here? How does the Andersen
> > > solver decide to fill those sets?
>
> the indirect call.
>
> Richard.
In the meantime I've managed to get GDB into the place where the
ix86_encode_section_info.arg1 gets filled. I'll try to step through the
Andersen solver and see if I can figure out what's going on that way. Here's
the stack trace in case you're interested:
#0 bitmap_list_insert_element_after (head=<optimized out>, elt=elt@entry=0x0,
indx=<optimized out>,
node=0x5b64bb0, node@entry=0x0) at ../../thesis-src/gcc/bitmap.cc:328
#1 0x0000000000aa77d6 in bitmap_elt_copy (dst=<optimized out>,
dst_elt=<optimized out>, dst_prev=0x0,
src_elt=0x5bbefb8, changed=true) at ../../thesis-src/gcc/bitmap.cc:1506
#2 bitmap_elt_ior (dst=<optimized out>, dst_elt=<optimized out>, dst_prev=0x0,
a_elt=<optimized out>,
b_elt=<optimized out>, changed=<optimized out>) at
../../thesis-src/gcc/bitmap.cc:2055
#3 0x0000000000aaac19 in bitmap_ior_into (a=0x3c4be50, b=b@entry=0x3f2c410)
at ../../thesis-src/gcc/bitmap.cc:2131
#4 0x00000000013df790 in solve_graph (graph=0x3b38ef0) at
../../thesis-src/gcc/pta-andersen.cc:2385
2377 {
2378 to_remove = j;
2379 if (bitmap_set_bit (get_varinfo (to)->solution,
2380 escaped_id))
2381 bitmap_set_bit (changed, to);
2382 continue;
2383 }
2384
2385 if (bitmap_ior_into (get_varinfo (to)->solution,
pts)) <----------------
2386 bitmap_set_bit (changed, to);
2387 }
2388 if (to_remove != ~0U)
2389 bitmap_clear_bit (graph->succs[i], to_remove);
2390 }
2391 }
Thanks,
Filip