In order to keep the number of state edges manageable, and make it clear to later passes that memory is constant, we currently avoid routing any memory states for constant memory locations.
For many loads, this allows SVF to instead trace the address of the load back to a delta node. Since the memory is constant, the initializer of the delta node can be directly copied into the region of, and replace, the load node.
However, some loads from constant memory originate from imported symbols, such as in the following C program:
extern const int a;
int func()
{
if(a != 0)
return a;
return 0;
}
If we were to route a memory state through all references to a, the load inside the if would be traced back to the first load, and be replaced through forwarding in the SVF pass. However, since we know that a is constant, there are no memory state edges in this function. Since a is imported, SVF is not able to replace all loads, but we would still like to replace the inner load.
The RVSDG looks like this:

There are multiple ways this could be resolved:
- Route memory states through constant memory after all, but skip propagating them through calls? Maybe do this but only for imported symbols, not symbols defined in with delta nodes? Not really a clean solution.
- Remove IO Barriers from these load operations, since we know that symbols are always legal to load from (at least as long as we do not apply unknown pointer offsets), and let NodePushOut + CommonNodeElimination handle the duplicated loads.
- Make CommonNodeElimination slightly smarter, so that it is able to detect common nodes across parent and subregions, and do forwarding directly without needing to push nodes out first? I think this might be the best solution, since it is not always legal to push nodes out.
In order to keep the number of state edges manageable, and make it clear to later passes that memory is constant, we currently avoid routing any memory states for constant memory locations.
For many loads, this allows SVF to instead trace the address of the load back to a delta node. Since the memory is constant, the initializer of the delta node can be directly copied into the region of, and replace, the load node.
However, some loads from constant memory originate from imported symbols, such as in the following C program:
If we were to route a memory state through all references to
a, the load inside theifwould be traced back to the first load, and be replaced through forwarding in the SVF pass. However, since we know thatais constant, there are no memory state edges in this function. Sinceais imported, SVF is not able to replace all loads, but we would still like to replace the inner load.The RVSDG looks like this:

There are multiple ways this could be resolved: