We should not fold one of add/sub operands into a load/store's offset when `nuw` (no unsigned wrap) is not present, because the address calculation, which adds the offset with the operand, does not wrap. This is handled correctly in the normal ISel:6de5305b3d/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp (L328-L332)but not in FastISel. This positivity check in FastISel is not sufficient to avoid this case fully:6de5305b3d/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (L348-L352)because 1. Even if RHS is within signed int range, depending on the value of the LHS, the resulting value can exceed uint32 max. 2. When one of the operands is a label, `Address` can contain a `GlobalValue` and a `Reg` at the same time, so the `GlobalValue` becomes incorrectly an offset:6de5305b3d/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (L53-L69)6de5305b3d/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (L409-L417)Both cases are in the newly added test. We should handle `SUB` too because `SUB` is the same as `ADD` when RHS's sign changes. I checked why our current normal ISel only handles `ADD`, and the reason it's OK for the normal ISel to handle only `ADD` seems that DAGCombiner replaces `SUB` with `ADD` here:6de5305b3d/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (L3904-L3907)Fixes #111018.
42 KiB
42 KiB