The existing rule about the operand type is strange. Instead, just say the operand is a TargetConstant with the right width. (Legalization ignores TargetConstants, so it doesn't matter if that width is legal.)
Highlights:
- I had to substantially rewrite the AArch64 isel patterns to expect a TargetConstant. Nothing too exotic, but maybe a little hairy. Maybe worth considering a target-specific node with some dagcombines instead of this complicated nest of isel patterns.
- Our behavior on RV32 for vectors of i64 has changed slightly. In particular, we correctly preserve the width of the arithmetic through legalization. The result is a bit ugly in some cases.
- I explicitly defined the behavior around overflow. This is necessary to make the DAGCombine transforms legal, and I don't think it causes any practical issues.
We couldn't do this before because the type of Step was important. This is no longer the case so is it worth giving StepVal a default of 1? as a connivence. I know there's the assert that the sizes match but adding || StepVal.isOneValue() doesn't seem so bad.