Hello! Attached patch introduces bswaphi2 named insn pattern that results in movbe instruction.
Without the patch, the following testcase: void baz (char *buf, unsigned int data) { buf[0] = data >> 8; buf[1] = data; } compiles to (-O2 -march=haswell): rolw $8, %si movw %si, (%rdi) and with patched compiler: movbe %si, (%rdi) 2017-11-20 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.md (bswaphi2): New expander. (*bswaphi2_movbe): New insn pattern. (bswaphi -> rorhi pepehole2): New peephole pattern. testsuite/ChangeLog: 2017-11-20 Uros Bizjak <ubiz...@gmail.com> Jakub Jelinek <ja...@redhat.com> * gcc.target/i386/movbe-5.c: New test. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 254958) +++ config/i386/i386.md (working copy) @@ -14091,6 +14091,39 @@ (set_attr "modrm" "0") (set_attr "mode" "<MODE>")]) +(define_expand "bswaphi2" + [(set (match_operand:HI 0 "register_operand") + (bswap:HI (match_operand:HI 1 "nonimmediate_operand")))] + "TARGET_MOVBE") + +(define_insn "*bswaphi2_movbe" + [(set (match_operand:HI 0 "nonimmediate_operand" "=Q,r,m") + (bswap:HI (match_operand:HI 1 "nonimmediate_operand" "0,m,r")))] + "TARGET_MOVBE + && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "@ + xchg{b}\t{%h0, %b0|%b0, %h0} + movbe\t{%1, %0|%0, %1} + movbe\t{%1, %0|%0, %1}" + [(set_attr "type" "imov") + (set_attr "modrm" "*,1,1") + (set_attr "prefix_0f" "*,1,1") + (set_attr "prefix_extra" "*,1,1") + (set_attr "pent_pair" "np,*,*") + (set_attr "athlon_decode" "vector,*,*") + (set_attr "amdfam10_decode" "double,*,*") + (set_attr "bdver1_decode" "double,*,*") + (set_attr "mode" "QI,HI,HI")]) + +(define_peephole2 + [(set (match_operand:HI 0 "general_reg_operand") + (bswap:HI (match_dup 0)))] + "TARGET_MOVBE + && !(TARGET_USE_XCHGB || optimize_function_for_size_p (cfun)) + && peep2_regno_dead_p (0, FLAGS_REG)" + [(parallel [(set (match_dup 0) (rotate:HI (match_dup 0) (const_int 8))) + (clobber (reg:CC FLAGS_REG))])]) + (define_insn "*bswaphi_lowpart_1" [(set (strict_low_part (match_operand:HI 0 "register_operand" "+Q,r")) (bswap:HI (match_dup 0))) Index: testsuite/gcc.target/i386/movbe-5.c =================================================================== --- testsuite/gcc.target/i386/movbe-5.c (nonexistent) +++ testsuite/gcc.target/i386/movbe-5.c (working copy) @@ -0,0 +1,18 @@ +/* PR tree-optimization/78821 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mmovbe" } */ +/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 } } */ + +unsigned short +foo (unsigned short *buf) +{ + unsigned short a = buf[0]; + return ((unsigned short) (a >> 8)) | (unsigned short) (a << 8); +} + +void +bar (char *buf, unsigned int data) +{ + buf[0] = data >> 8; + buf[1] = data; +}