Implement support for matching an index from a WebAssembly CALL
instruction. Add test.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/test/CodeGen/WebAssembly/externref-tableset.ll | ||
---|---|---|
82 | Is this returning the ID of a table, or the ID of slot within a table? I seem like its the latter, in which case maybe its name is a little confusing? How about calling this get_table_slot ? |
I think this needs to be more generic, rather than allowing just calls... as I found a similar problem when the node is a CopyFromReg. I will refactor this patch.
llvm/test/CodeGen/WebAssembly/externref-tableset.ll | ||
---|---|---|
82 | You're right, it's the latter. I will rename. |
Make the fix slightly more generic. I have found while writing LLVM IR with lots of usage of store and loads on reference types and intrinsics, that there are several cases where the Idx to the table can be the result of a call or copy from reg, etc. These have 2 values, the main value and the chain so checking if the Idx has a single value is the wrong approach. This seems to work as by default we use the first value of the Node and we don't need to impose any restrictions on it. The only case this could possibly fail is if we get a Node whose value we want to use is not the first value but I cannot imagine a case where that could happen and I didn't come accross it.
Code LGTM, but I don't quite understand what the bug was, so I'm not sure about the test coverage.
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
1493–1494 | Does the test in this revision cover this Idx.isUndef() case? I would have expected to see an undef in the IR. |
I should have definitely explained this better, I am sorry.
In the C++ code matching a LowerStore or LowerLoad from a table global into TABLE_GET or TABLE_SET, we used to check that the Idx variable for the table access, i.e. the indice into the table has only one value (checks for Idx->getNumValues() != 1 and doesn't lower it if true). In one of the cases I am translating from the milestones work (https://github.com/Igalia/ref-cpp/blob/13537129e16a48fc62ad719f63fe592d11ae6d2f/milestones/m3/test.ll#L137) the index of the table comes from a call to a function. The call however doesn't have a single value though, it has two. One for the return value and one for the chain and therefore LLVM was not lowering the node and instead it was failing during selection. I didn't do anything special besides removing the check for single-valuedness from Idx, which works. I am not 100% sure it always works though, so if you can think of another time when this wouldn't work, it would be great to know. For example, the way it currently works is that if the node has more than one value, then the first value is used. Since chains are the last value, this works for calls but it would fall apart if there's a node for which the value that contains the indice into the table is not in first value position. I can't however think of a situation where this would happen.
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
1493–1494 | Yes, good point. I should write a test covering this case. |
Remove isUndef check from code. I cannot find a codepath that generates an undef Idx at this point. All undef values end up being propogated down to the respective GEP. So simplifying and removing check.
An example situation where there might be more than one value is in a multivalue call, but Idx should only refer to whichever value is actually used as the offset and I agree that it shouldn't matter whether there are other values in the same node or not.
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
1493–1494 | Should this just be an assertion? I would be surprised if a GlobalAddressSDNode could ever have more than one value. |
Does the test in this revision cover this Idx.isUndef() case? I would have expected to see an undef in the IR.