-
Notifications
You must be signed in to change notification settings - Fork 3
fix!: Allow Const and FuncDecl as children of Modules, Dataflow Parents, and CFG nodes #46
Conversation
5ec8d0e
to
65e5d8c
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #46 +/- ##
==========================================
+ Coverage 82.19% 83.12% +0.93%
==========================================
Files 16 16
Lines 2190 2234 +44
Branches 2190 2234 +44
==========================================
+ Hits 1800 1857 +57
+ Misses 258 246 -12
+ Partials 132 131 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
store { i32, {}, {} } %"12_01", { i32, {}, {} }* %"4_0", align 4 | ||
%"4_02" = load { i32, {}, {} }, { i32, {}, {} }* %"4_0", align 4 | ||
store { i32, {}, {} } %"4_02", { i32, {}, {} }* %"0", align 4 | ||
%"03" = load { i32, {}, {} }, { i32, {}, {} }* %"0", align 4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any idea why we end up with all these redundant store and load cycles?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we make no attempt to avoid them. Before we emit a node we load a value per input wire, then after we emit a node we store one value per output wire. Sometimes (for example Exit
nodes) we even store and load to intermediate alloca
s that do not correspond to wires in the graph.
mem2reg
removes these. There are(should be) no difficult cases because the value in the alloca
is always unique.
We could potentially avoid emitting (most of) them, but this would make things more complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! 😄
src/emit/snapshots/hugr_llvm__emit__test__multiple_funcs@llvm14.snap
Outdated
Show resolved
Hide resolved
br label %2 | ||
|
||
0: ; preds = %2 | ||
%1 = extractvalue { {} } undef, 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any idea what's going on here? Just for my personal curiosity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this corresponds to the let control = builder.add_load_value(Value::unary_unit_sum());
line. The out wire of this is of type "unary sum with one variant", which we encode in llvm as { {} }
: a struct containing an empty struct. Normally Sum types also have an i32
tag, but when num_variants <= 1, we omit the tag. When we generate the code for the following switch, we "read the tag", which for this case(num_variants <= 1), just creates a value with constant value 0
.
Obviously this looks dumb, it is the result of lowering the ops in a uniform way, with the goal of making the code here simple. The cost is that you generate dumb code. We do expect LLVM to be able to clean this up easily. In this case "dce" (dead-code-elimination) will delete %1 as it's unused and side-effect-free.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Doug, makes perfect sense!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that's not quite the right explanation. When we switch at the end of a DataFlowBlock
we must write to the RowMailBox
of the target block. Note that this write has to happen AFTER the switch, because we only do it on the taken edge. When we write to that RowMailBox
we first write each value in the Sum (which has a known variant tag because we are after the switch), then we write each of the "other inputs" (of the Output node in the Block we just left). So we extractvalue
the struct of our variant from the struct representing the Sum
. Then for each field in the struct, we extractvalue
that and write it to the mail box. In this case, the struct of our variant is {}
i.e. empty and there are no "other inputs", so the only thing we do is extractvalue
the struct of our variant, which is what this line is.
## 🤖 New release * `hugr-llvm`: 0.1.0 <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [0.1.0](https://github.com/CQCL/hugr-llvm/releases/tag/v0.1.0) - 2024-07-10 ### Bug Fixes - Syntax error - sum type tag elision logic reversed - [**breaking**] Allow Const and FuncDecl as children of Modules, Dataflow Parents, and CFG nodes ([#46](#46)) ### Documentation - fix bad grammar ([#34](#34)) ### New Features - Emission for Call nodes - Support values - add `get_extern_func` ([#28](#28)) - lower CFGs ([#26](#26)) - Add initial codegen extension for `prelude` ([#29](#29)) - [**breaking**] `Namer` optionally appends node index to mangled names. ([#32](#32)) - Implement lowerings for ieq,ilt_s,sub in int codegen extension ([#33](#33)) - Add initial `float` extension ([#31](#31)) - Emit more int comparison operators ([#47](#47)) ### Refactor - clean up fat.rs ([#38](#38)) ### Testing - add a test for sum type tags - Add integration tests lowering guppy programs ([#35](#35)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/MarcoIeni/release-plz/). --------- Co-authored-by: Douglas Wilson <douglas.wilson@quantinuum.com>
We take the opportunity to fix a bug where the promise to ignore duplicate calls to
emit_func
was not upheld, and to clean up the now unnecessaryEmission
.Fixes #4 , although we go further than required by this issue.
BREAKING CHANGE: rename
emit_global
toemit_func
. ReplaceEmission
type withFatNode<FuncDefn>
.