Open komaljai opened 1 month ago
It is not incorrect, just inefficient.
The copy is introduced by inlining which is not smart enough to determine that hdr
(argument to Deparser) cannot possibly be modified/accessed by code in the ipip_push function. Improving the code I added in #4877 might be able to fix this.
LocalCopyProp is likewise not smart enough to do this. It might propagate the hdr_1 = hdr
assignment into the first inner
assignment (making it hdr_1.inner = hdr.outer
), but that would kill the copy (hdr1 partly overwritten) so would not be able to copyprop any of the subsequent uses.
From an end user's perspective, there's currently an inconsistency between how controls and functions are inlined.
Compiling the code referenced by @komaljai yields this at the end of FrontEnd:
control Deparser(packet_out pkt, inout headers_t hdr, in metadata_t meta, in pna_main_output_metadata_t ostd) {
@name("Deparser.hdr_0") headers_t hdr_1;
@name("Deparser.meta_0") metadata_t meta_1;
apply {
pkt.emit<ethernet_t>(hdr.ethernet);
if (meta.push && hdr.outer.isValid()) {
hdr_1 = hdr;
meta_1 = meta;
hdr_1.inner = hdr_1.outer;
...
hdr_1.outer.hdrChecksum = 16w0;
hdr = hdr_1;
}
pkt.emit<ipv4_t>(hdr.outer);
pkt.emit<ipv4_t>(hdr.inner);
}
}
But if we change the ipip_push
function to a control, then we get:
control Deparser(packet_out pkt, inout headers_t hdr, in metadata_t meta, in pna_main_output_metadata_t ostd) {
apply {
pkt.emit<ethernet_t>(hdr.ethernet);
if (meta.push && hdr.outer.isValid()) {
hdr.inner = hdr.outer;
...
hdr.outer.hdrChecksum = 16w0;
}
pkt.emit<ipv4_t>(hdr.outer);
pkt.emit<ipv4_t>(hdr.inner);
}
}
The core of the inlining is performed by Inline
for the control case and InlineFunctions
for the function case.
From an end user's perspective, there's currently an inconsistency between how controls and functions are inlined.
This is because controls cannot be nested in controls (or functions) and functions cannot be nested in functions, but functions CAN be nested in controls. So the code to not introduce the copies would have to have an extra check that the function was not nested in the control.
This is because controls cannot be nested in controls (or functions) and functions cannot be nested in functions, but functions CAN be nested in controls. So the code to not introduce the copies would have to have an extra check that the function was not nested in the control.
Do you have a short example of P4 code that p4c compiles today, where a function is nested in a control? I tried to create one, but get an error if I attempt to define a function inside the body of a control.
Maybe a so-called "abstract function" that has support, originally for associating a behavior with TNA register actions? Example: https://github.com/p4lang/p4app-switchML/blob/main/dev_root/p4/workers_counter.p4#L27-L39
The IR representation at end of frontend looks like -
The issue is copy propogation, 'hdr' is assigned to 'hdr1' in beginning and 'hdr1' is assigned to 'hdr' back at the end, Shouldn't this be optimized?