https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98856

--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
V4DImode arithmetic right shifts would be (untested):
--- gcc/config/i386/sse.md.jj   2021-02-05 14:32:44.175463716 +0100
+++ gcc/config/i386/sse.md      2021-02-05 15:24:37.942026401 +0100
@@ -12458,7 +12458,7 @@
    (set_attr "prefix" "orig,vex")
    (set_attr "mode" "<sseinsnmode>")])

-(define_insn "ashr<mode>3<mask_name>"
+(define_insn "<mask_codefor>ashr<mode>3<mask_name>"
   [(set (match_operand:VI248_AVX512BW_AVX512VL 0 "register_operand" "=v,v")
        (ashiftrt:VI248_AVX512BW_AVX512VL
          (match_operand:VI248_AVX512BW_AVX512VL 1 "nonimmediate_operand"
"v,vm")
@@ -12472,6 +12472,67 @@
        (const_string "0")))
    (set_attr "mode" "<sseinsnmode>")])

+(define_expand "ashr<mode>3"
+  [(set (match_operand:VI248_AVX512BW 0 "register_operand")
+       (ashiftrt:VI248_AVX512BW
+         (match_operand:VI248_AVX512BW 1 "nonimmediate_operand")
+         (match_operand:DI 2 "nonmemory_operand")))]
+  "TARGET_AVX512F")
+
+(define_expand "ashrv4di3"
+  [(set (match_operand:V4DI 0 "register_operand")
+       (ashiftrt:V4DI
+         (match_operand:V4DI 1 "nonimmediate_operand")
+         (match_operand:DI 2 "nonmemory_operand")))]
+  "TARGET_AVX2"
+{
+  if (!TARGET_AVX512VL)
+    {
+      if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 63)
+       {
+         rtx zero = force_reg (V4DImode, CONST0_RTX (V4DImode));
+         emit_insn (gen_avx2_gtv4di3 (operands[0], zero, operands[1]));
+         DONE;
+       }
+      if (operands[2] == const0_rtx)
+       {
+         emit_move_insn (operands[0], operands[1]);
+         DONE;
+       }
+
+      rtx zero = force_reg (V4DImode, CONST0_RTX (V4DImode));
+      rtx zero_or_all_ones = gen_reg_rtx (V4DImode);
+      emit_insn (gen_avx2_gtv4di3 (zero_or_all_ones, zero, operands[1]));
+      rtx lshr_res = gen_reg_rtx (V4DImode);
+      emit_insn (gen_lshrv4di3 (lshr_res, operands[1], operands[2]));
+      rtx ashl_res = gen_reg_rtx (V4DImode);
+      rtx amount;
+      if (CONST_INT_P (operands[2]))
+       amount = GEN_INT (64 - INTVAL (operands[2]));
+      else if (TARGET_64BIT)
+       {
+         amount = gen_reg_rtx (DImode);
+         emit_insn (gen_subdi3 (amount, force_reg (DImode, GEN_INT (64)),
+                                operands[2]));
+       }
+      else
+       {
+         rtx temp = gen_reg_rtx (SImode);
+         emit_insn (gen_subsi3 (temp, force_reg (SImode, GEN_INT (64)),
+                                lowpart_subreg (SImode, operands[2],
+                                                DImode)));
+         amount = gen_reg_rtx (V4SImode);
+         emit_insn (gen_vec_setv4si_0 (amount, CONST0_RTX (V4SImode),
+                                       temp));
+       }
+      if (!CONST_INT_P (operands[2]))
+       amount = lowpart_subreg (DImode, amount, GET_MODE (amount));
+      emit_insn (gen_ashlv4di3 (ashl_res, zero_or_all_ones, amount));
+      emit_insn (gen_iorv4di3 (operands[0], lshr_res, ashl_res));
+      DONE;
+    }
+})
+
 (define_insn "<mask_codefor><insn><mode>3<mask_name>"
   [(set (match_operand:VI248_AVX512BW_2 0 "register_operand" "=v,v")
        (any_lshift:VI248_AVX512BW_2

Trying 3 different routines, one returning >> 63 of a V4DImode vector, another
one >> 17 and another one >> var, the differences with -mavx2 are:
-       vextracti128    $0x1, %ymm0, %xmm1
-       vmovq   %xmm0, %rax
-       vpextrq $1, %xmm0, %rcx
-       cqto
-       vmovq   %xmm1, %rax
-       sarq    $63, %rcx
-       sarq    $63, %rax
-       vmovq   %rdx, %xmm3
-       movq    %rax, %rsi
-       vpextrq $1, %xmm1, %rax
-       vpinsrq $1, %rcx, %xmm3, %xmm0
-       sarq    $63, %rax
-       vmovq   %rsi, %xmm2
-       vpinsrq $1, %rax, %xmm2, %xmm1
-       vinserti128     $0x1, %xmm1, %ymm0, %ymm0
+       vmovdqa %ymm0, %ymm1
+       vpxor   %xmm0, %xmm0, %xmm0
+       vpcmpgtq        %ymm1, %ymm0, %ymm0

-       vmovq   %xmm0, %rax
-       vextracti128    $0x1, %ymm0, %xmm1
-       vpextrq $1, %xmm0, %rcx
-       sarq    $17, %rax
-       sarq    $17, %rcx
-       movq    %rax, %rdx
-       vmovq   %xmm1, %rax
-       sarq    $17, %rax
-       vmovq   %rdx, %xmm3
-       movq    %rax, %rsi
-       vpextrq $1, %xmm1, %rax
-       vpinsrq $1, %rcx, %xmm3, %xmm0
-       sarq    $17, %rax
-       vmovq   %rsi, %xmm2
-       vpinsrq $1, %rax, %xmm2, %xmm1
-       vinserti128     $0x1, %xmm1, %ymm0, %ymm0
+       vpxor   %xmm1, %xmm1, %xmm1
+       vpcmpgtq        %ymm0, %ymm1, %ymm1
+       vpsrlq  $17, %ymm0, %ymm0
+       vpsllq  $47, %ymm1, %ymm1
+       vpor    %ymm1, %ymm0, %ymm0

and

-       movl    %edi, %ecx
-       vmovq   %xmm0, %rax
-       vextracti128    $0x1, %ymm0, %xmm1
-       sarq    %cl, %rax
-       vpextrq $1, %xmm0, %rsi
-       movq    %rax, %rdx
-       vmovq   %xmm1, %rax
-       sarq    %cl, %rsi
-       sarq    %cl, %rax
-       vmovq   %rdx, %xmm3
-       movq    %rax, %rdi
-       vpextrq $1, %xmm1, %rax
-       vpinsrq $1, %rsi, %xmm3, %xmm0
-       sarq    %cl, %rax
+       vpxor   %xmm1, %xmm1, %xmm1
+       movslq  %edi, %rdi
+       movl    $64, %eax
+       vpcmpgtq        %ymm0, %ymm1, %ymm1
+       subq    %rdi, %rax
        vmovq   %rdi, %xmm2
-       vpinsrq $1, %rax, %xmm2, %xmm1
-       vinserti128     $0x1, %xmm1, %ymm0, %ymm0
+       vmovq   %rax, %xmm3
+       vpsrlq  %xmm2, %ymm0, %ymm0
+       vpsllq  %xmm3, %ymm1, %ymm1
+       vpor    %ymm1, %ymm0, %ymm0

so at least size-wise much smaller.

Reply via email to