When I take a look at the combine pattern, I see a lot of haveOneUse. But I’m not quite sure if there are any principles that can simply indicate which scenarios are needed ?
- If no constraints for the pattern to be matched , the function may be at risk.
- while adding too much may limit unnecessary scenes.
In my personal experience, if a new expression is simply constructed based on some existing nodes and returned after pattern matching, there is no need to haveOneUse, and if there is a need to update more nodes such as replaceAllUsesWith or CombineTo, we need to use haveOneUse to ensure function correctness. I don’t know if my understanding is correct.
There are two cases where hasOneUse() may be necessary:
- Correctness: This is pretty unusual nowadays, but if a transform modifies a non-root instruction (rather than creating a new one), then the one-use check may be necessary for correctness (the modification may not be correct if there are other uses).
- Profitability: This is the far more common case. InstCombine has a rule of thumb that transforms should not increase the number of instructions. If you have a transform that replaces one instruction with another, you don’t need a one-use check. If you have a transform that replaces two instructions with two instructions, then you do need a one-use check, to ensure that both of the original instructions can be removed. Otherwise, we may remove only one of the original instructions (because the other has an extra use) and introduce two new ones. This is only a rule of thumb, and we do deviate from it occasionally (e.g. we are fine with replacing divisions with multiple instructions.)