RFR: 8347459: C2: missing transformation for chain of shifts/multiplications by constants

Jasmine Karthikeyan jkarthikeyan at openjdk.org
Fri Feb 21 19:13:55 UTC 2025


On Fri, 21 Feb 2025 15:57:30 GMT, Marc Chevalier <duke at openjdk.org> wrote:

> This collapses double shift lefts by constants in a single constant: (x << con1) << con2 => x << (con1 + con2). Care must be taken in the case con1 + con2 is bigger than the number of bits in the integer type. In this case, we must simplify to 0.
> 
> Moreover, the simplification logic of the sign extension trick had to be improved. For instance, we use `(x << 16) >> 16` to convert a 32 bits into a 16 bits integer, with sign extension. When storing this into a 16-bit field, this can be simplified into simple `x`. But in the case where `x` is itself a left-shift expression, say `y << 3`, this PR makes the IR looks like `(y << 19) >> 16` instead of the old `((y << 3) << 16) >> 16`. The former logic didn't handle the case where the left and the right shift have different magnitude. In this PR, I generalize this simplification to cases where the left shift has a larger magnitude than the right shift. This improvement was needed not to miss vectorization opportunities: without the simplification, we have a left shift and a right shift instead of a single left shift, which confuses the type inference.
> 
> This also works for multiplications by powers of 2 since they are already translated into shifts.
> 
> Thanks,
> Marc

This is a nice improvement! I'm glad to see that the limitation of Store/Shift folding requiring both shifts to have the same constant is being fixed. I've left some comments here.

I also noticed that in `LShiftINode::Ideal`, there is a transform that mentions not breaking `i2s` and `i2b` patterns. It might be worth looking separately to see if this condition can be relaxed because of the change to `StoreNode::Ideal_sign_extended_input`.

src/hotspot/share/opto/memnode.cpp line 3574:

> 3572: // StoreB ... (RShiftI _ (LShiftI _ (LShiftI _ valIn (conIL - conIR)) conIR ) conIR)
> 3573: Node* StoreNode::Ideal_sign_extended_input(PhaseGVN* phase, int num_rejected_bits) {
> 3574:   Node *val = in(MemNode::ValueIn);

It might be good to clean up the other 4 lines in this function to match current style guidelines while you're updating it.

src/hotspot/share/opto/mulnode.cpp line 981:

> 979: // con0 is assumed to be masked already (as computed by maskShiftAmount) and non-zero
> 980: // bt must be T_LONG or T_INT.
> 981: static Node* collapseDoubleShiftLeft(PhaseGVN* phase, Node* outer_shift, int con0, BasicType bt) {

>From the style guide, functions and local variables are named with `snake_case`. Maybe it could be named `collapse_left_shifts`.

src/hotspot/share/opto/mulnode.cpp line 986:

> 984:   Node* inner_shift = outer_shift->in(1);
> 985:   int inner_shift_op = inner_shift->Opcode();
> 986:   if (inner_shift_op != Op_LShift(bt)) {

Since the local variable is otherwise unused, it'd be simpler to do:
Suggestion:

  if (inner_shift->Opcode() != Op_LShift(bt)) {

src/hotspot/share/opto/mulnode.cpp line 996:

> 994: 
> 995:   if (con0 + con1 >= nbits) {
> 996:     return ConNode::make(TypeInteger::zero(bt));

It'd be clearer to do this, which is more equivalent but more concise:
Suggestion:

    return phase->zerocon(bt);

src/hotspot/share/opto/mulnode.cpp line 1018:

> 1016: // constant, flatten the tree: (X+con1)<<con0 ==> X<<con0 + con1<<con0
> 1017: //
> 1018: // (X << con1) << con2 ==> X << (con1 + con2) (see collapseDoubleShiftLeft for details)

I think it would be better to move this comment where `collapseDoubleShiftLeft` is called in the Ideal function, and same for `LShiftLNode::Ideal`.

-------------

PR Review: https://git.openjdk.org/jdk/pull/23728#pullrequestreview-2633935484
PR Review Comment: https://git.openjdk.org/jdk/pull/23728#discussion_r1966017369
PR Review Comment: https://git.openjdk.org/jdk/pull/23728#discussion_r1966021220
PR Review Comment: https://git.openjdk.org/jdk/pull/23728#discussion_r1966018379
PR Review Comment: https://git.openjdk.org/jdk/pull/23728#discussion_r1966004662
PR Review Comment: https://git.openjdk.org/jdk/pull/23728#discussion_r1966006840


More information about the hotspot-compiler-dev mailing list