On Wed, Jul 17, 2019 at 12:00:32PM -0500, Segher Boessenkool wrote: > I think we can say that *all* targets behave like SHIFT_COUNT_TRUNCATED > for rotates? Not all immediates are valid of course, but that is a > separate issue.
Well, we'd need to double check all the hw rotate instructions on all the targets to be sure. As for the current GCC code, SHIFT_COUNT_TRUNCATED value is used even for rotates at least in combine.c, expmed.c and simplify-rtx.c and in optabs.c through targetm.shift_truncation_mask, but e.g. in cse.c is used only for shifts and not rotates. And speaking of optabs.c, it already has code to emit the other rotate if one rotate isn't supported, the: /* If we were trying to rotate, and that didn't work, try rotating the other direction before falling back to shifts and bitwise-or. */ if (((binoptab == rotl_optab && (icode = optab_handler (rotr_optab, mode)) != CODE_FOR_nothing) || (binoptab == rotr_optab && (icode = optab_handler (rotl_optab, mode)) != CODE_FOR_nothing)) && is_int_mode (mode, &int_mode)) { optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab); hunk in there, just it is limited to scalar rotates ATM rather than vector ones through is_int_mode. So I bet the problem with the vector shifts is just that tree-vect-generic.c support isn't there. And the above mentioned code actually emits the newop1 = expand_binop (GET_MODE (op1), sub_optab, gen_int_mode (bits, GET_MODE (op1)), op1, NULL_RTX, unsignedp, OPTAB_DIRECT); as the fallback, rather than masking of negation with some mask, so if there is some target that doesn't truncate the rotate count, it will be problematic with variable rotate by 0. And note that the other rotate code explicitly uses targetm.shift_truncation_mask. Jakub