[interp] Squash multiple call args moves into single opcode (#52242)
* [interp] Replace multiplication and division by 1 with simple mov
* [interp] Skip emitting redundant branch to next basic block
* [interp] Squash multiple call args moves into single opcode
Some vars cannot be used directly as an argument to another call. In this case, the var offset allocator generates new intermediary vars. For methods with a lot of parameters, we can end up with quite a lot of these stores.
As an example, for the following method:
```
public static void MethodPartial (int a, int b, object c, object d)
{
MethodFull (a, b, c, d, 12523);
}
```
Before:
```
IR_0000: ldc.i8 [72 <- nil], 12523
IR_0006: mov.4 [40 <- 0],
IR_0009: mov.4 [48 <- 8],
IR_000c: mov.8 [56 <- 16],
IR_000f: mov.8 [64 <- 24],
IR_0012: call [32 <- 40], 0
IR_0016: ret.void [nil <- nil],
```
After:
```
IR_0000: ldc.i8 [72 <- nil], 12523
IR_0006: mov.8.4 [nil <- nil], 40 <- 0, 48 <- 8, 56 <- 16, 64 <- 24
IR_000f: call [32 <- 40], 0
IR_0013: ret.void [nil <- nil]
```