https://gcc.gnu.org/g:cc195978102e2076c4426b4dfbe457d2f223ae83
commit r17-4875-gcc195978102e2076c4426b4dfbe457d2f223ae83 Author: Roger Sayle <[email protected]> Date: Sun Oct 4 19:58:11 2026 +0100 i386: Ensure the x86 backend is any-or-plus (AOP) safe. This patch tweaks i386.md to ensure that it is AOP-safe, i.e. can recognize shld and shrd instructions when expressed in RTL using either PLUS, IOR or XOR. This is a pre-requisite to fixing PR tree-optimization/108477. This patch also documents aop_optab by definining and describing the aop<mode>3 named pattern (as requested by Richard Biener). 2026-10-04 Roger Sayle <[email protected]> Uros Bizjak <[email protected]> gcc/ChangeLog * config/i386/i386.md: Various whitespace and indentation clean-ups. (aop_name_pfx): New code attribute to produce "*" for XOR/PLUS. (x86_64_shld<nf_name>): Use any_or_plus and aop_name_pfx. (x86_64_shld_ndd<nf_name>): Likewise. (x86_64_shld_1<nf_name>): Likewise. (x86_64_shld_ndd_1<nf_name>): Likewise. (*x86_64_shld_shrd_1_nozext_nf): Use any_or_plus. (*x86_64_shld_shrd_1_nozext): Likewise. (*x86_64_shld_2): Likewise. (*x86_64_shld_ndd_2): Likewise. (x86_shld<nf_name>): Use any_or_plus and aop_name_pfx. (x86_shld_1<nf_name>): Likewise. (x86_shld_ndd_1<nf_name>): Likewise. (*x86_shld_shrd_1_nozext_nf): Use any_or_plus. (*x86_shld_shrd_1_nozext): Likewise. (*x86_shld_2): Likewise. (*x86_shld_ndd_2): Likewise. (x86_64_shrd<nf_name>): Use any_or_plus and aop_name_pfx. (x86_64_shrd_ndd<nf_name>): Likewise. (x86_64_shrd_1<nf_name>): Likewise. (x86_64_shrd_ndd_1<nf_name>): Likewise. (*x86_64_shrd_shld_1_nozext_nf): Use any_or_plus. (*x86_64_shrd_shld_1_nozext): Likewise. (*x86_64_shrd_2): Likewise. (*x86_64_shrd_ndd_2): Likewise. Fix match_dup operand numbering. (x86_shrd<nf_name>): Use any_or_plus and aop_name_pfx. (x86_shrd_ndd<nf_name>): Likewise. (x86_shrd_1<nf_name>): Likewise. (x86_shrd_ndd_1<nf_name>): Likewise. (*x86_shrd_shld_1_nozext_nf): Use any_or_plus. (*x86_shrd_shld_1_nozext): Likewise. (*x86_shrd_2): Likewise. (*x86_shrd_ndd_2): Likewise. * doc/md.texi: Document aop<mode>3 as a named pattern. Diff: --- gcc/config/i386/i386.md | 603 +++++++++++++++++++++++++----------------------- gcc/doc/md.texi | 16 ++ 2 files changed, 327 insertions(+), 292 deletions(-) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 0d4749e6e091..2106e6b56acf 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1226,7 +1226,7 @@ ;; Math-dependant single word integer modes without QImode. (define_mode_iterator SWIM248 [(HI "TARGET_HIMODE_MATH") - SI (DI "TARGET_64BIT")]) + SI (DI "TARGET_64BIT")]) ;; Double word integer modes. (define_mode_iterator DWI [(DI "!TARGET_64BIT") @@ -3777,6 +3777,8 @@ (set_attr "mode" "QI")]) (define_code_iterator any_or_plus [plus ior xor]) +;; Name prefix for any_or_plus insns: only the IOR form keeps a gen_* function. +(define_code_attr aop_name_pfx [(ior "") (xor "*") (plus "*")]) (define_insn_and_split "*insvti_highpart_1" [(set (match_operand:TI 0 "nonimmediate_operand" "=ro,r,r,&r") @@ -16388,17 +16390,17 @@ (symbol_ref "TARGET_ENABLE_NDD_MEM")] (symbol_ref "true")))]) -(define_insn "x86_64_shld<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shld<nf_name>" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") - (ior:DI (ashift:DI (match_dup 0) - (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc") - (const_int 63))) - (subreg:DI - (lshiftrt:TI - (zero_extend:TI - (match_operand:DI 1 "register_operand" "r")) - (minus:QI (const_int 64) - (and:QI (match_dup 2) (const_int 63)))) 0)))] + (any_or_plus:DI + (ashift:DI (match_dup 0) + (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc") + (const_int 63))) + (subreg:DI + (lshiftrt:TI + (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) + (minus:QI (const_int 64) + (and:QI (match_dup 2) (const_int 63)))) 0)))] "TARGET_64BIT && <nf_condition>" "<nf_prefix>shld{q}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") @@ -16409,17 +16411,17 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shld_ndd<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shld_ndd<nf_name>" [(set (match_operand:DI 0 "register_operand" "=r,r") - (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m") - (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc,Jc") - (const_int 63))) - (subreg:DI - (lshiftrt:TI - (zero_extend:TI - (match_operand:DI 2 "register_operand" "r,r")) - (minus:QI (const_int 64) - (and:QI (match_dup 3) (const_int 63)))) 0)))] + (any_or_plus:DI + (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m") + (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc,Jc") + (const_int 63))) + (subreg:DI + (lshiftrt:TI + (zero_extend:TI (match_operand:DI 2 "register_operand" "r,r")) + (minus:QI (const_int 64) + (and:QI (match_dup 3) (const_int 63)))) 0)))] "TARGET_APX_NDD && <nf_condition>" "<nf_prefix>shld{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") @@ -16430,15 +16432,15 @@ (set_attr "has_nf" "1") (set_attr "mode" "DI")]) -(define_insn "x86_64_shld_1<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shld_1<nf_name>" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") - (ior:DI (ashift:DI (match_dup 0) - (match_operand:QI 2 "const_0_to_63_operand")) - (subreg:DI - (lshiftrt:TI - (zero_extend:TI - (match_operand:DI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_255_operand")) 0)))] + (any_or_plus:DI + (ashift:DI (match_dup 0) + (match_operand:QI 2 "const_0_to_63_operand")) + (subreg:DI + (lshiftrt:TI + (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) + (match_operand:QI 3 "const_0_to_255_operand")) 0)))] "TARGET_64BIT && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) && <nf_condition>" @@ -16452,15 +16454,15 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shld_ndd_1<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shld_ndd_1<nf_name>" [(set (match_operand:DI 0 "register_operand" "=r,r") - (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m") - (match_operand:QI 3 "const_0_to_63_operand")) - (subreg:DI - (lshiftrt:TI - (zero_extend:TI - (match_operand:DI 2 "register_operand" "r,r")) - (match_operand:QI 4 "const_0_to_255_operand")) 0)))] + (any_or_plus:DI + (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "r,m") + (match_operand:QI 3 "const_0_to_63_operand")) + (subreg:DI + (lshiftrt:TI + (zero_extend:TI (match_operand:DI 2 "register_operand" "r,r")) + (match_operand:QI 4 "const_0_to_255_operand")) 0)))] "TARGET_APX_NDD && INTVAL (operands[4]) == 64 - INTVAL (operands[3]) && <nf_condition>" @@ -16476,11 +16478,11 @@ (define_insn_and_split "*x86_64_shld_shrd_1_nozext_nf" [(set (match_operand:DI 0 "nonimmediate_operand") - (ior:DI (ashift:DI (match_operand:DI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_63_operand")) - (lshiftrt:DI - (match_operand:DI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_63_operand"))))] + (any_or_plus:DI + (ashift:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand"))))] "TARGET_64BIT && TARGET_APX_NF && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) && ix86_pre_reload_split ()" @@ -16518,24 +16520,24 @@ emit_move_insn (operands[0], tmp); } else - { - operands[1] = force_reg (DImode, operands[1]); - rtx tmp = gen_reg_rtx (DImode); - emit_move_insn (tmp, operands[4]); - emit_insn (gen_x86_64_shld_1_nf (tmp, operands[1], - operands[2], operands[3])); - emit_move_insn (operands[0], tmp); - } - DONE; + { + operands[1] = force_reg (DImode, operands[1]); + rtx tmp = gen_reg_rtx (DImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_64_shld_1_nf (tmp, operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; }) (define_insn_and_split "*x86_64_shld_shrd_1_nozext" [(set (match_operand:DI 0 "nonimmediate_operand") - (ior:DI (ashift:DI (match_operand:DI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_63_operand")) - (lshiftrt:DI - (match_operand:DI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_63_operand")))) + (any_or_plus:DI + (ashift:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) @@ -16547,48 +16549,52 @@ if (rtx_equal_p (operands[4], operands[0])) { operands[1] = force_reg (DImode, operands[1]); - emit_insn (gen_x86_64_shld_1 (operands[0], operands[1], operands[2], operands[3])); + emit_insn (gen_x86_64_shld_1 (operands[0], operands[1], + operands[2], operands[3])); } else if (rtx_equal_p (operands[1], operands[0])) { operands[4] = force_reg (DImode, operands[4]); - emit_insn (gen_x86_64_shrd_1 (operands[0], operands[4], operands[3], operands[2])); + emit_insn (gen_x86_64_shrd_1 (operands[0], operands[4], + operands[3], operands[2])); } else if (TARGET_APX_NDD) { - rtx tmp = gen_reg_rtx (DImode); - if (MEM_P (operands[4])) - { - operands[1] = force_reg (DImode, operands[1]); - emit_insn (gen_x86_64_shld_ndd_1 (tmp, operands[4], operands[1], - operands[2], operands[3])); - } - else if (MEM_P (operands[1])) - emit_insn (gen_x86_64_shrd_ndd_1 (tmp, operands[1], operands[4], - operands[3], operands[2])); - else - emit_insn (gen_x86_64_shld_ndd_1 (tmp, operands[4], operands[1], - operands[2], operands[3])); - emit_move_insn (operands[0], tmp); + rtx tmp = gen_reg_rtx (DImode); + if (MEM_P (operands[4])) + { + operands[1] = force_reg (DImode, operands[1]); + emit_insn (gen_x86_64_shld_ndd_1 (tmp, operands[4], operands[1], + operands[2], operands[3])); + } + else if (MEM_P (operands[1])) + emit_insn (gen_x86_64_shrd_ndd_1 (tmp, operands[1], operands[4], + operands[3], operands[2])); + else + emit_insn (gen_x86_64_shld_ndd_1 (tmp, operands[4], operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); } else - { - operands[1] = force_reg (DImode, operands[1]); - rtx tmp = gen_reg_rtx (DImode); - emit_move_insn (tmp, operands[4]); - emit_insn (gen_x86_64_shld_1 (tmp, operands[1], operands[2], operands[3])); - emit_move_insn (operands[0], tmp); - } - DONE; + { + operands[1] = force_reg (DImode, operands[1]); + rtx tmp = gen_reg_rtx (DImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_64_shld_1 (tmp, operands[1], operands[2], + operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; } [(set_attr "has_nf" "1")]) (define_insn_and_split "*x86_64_shld_2" [(set (match_operand:DI 0 "nonimmediate_operand") - (ior:DI (ashift:DI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand")) - (lshiftrt:DI (match_operand:DI 1 "register_operand") - (minus:QI (const_int 64) (match_dup 2))))) + (any_or_plus:DI + (ashift:DI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand")) + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (minus:QI (const_int 64) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_pre_reload_split ()" "#" @@ -16606,10 +16612,11 @@ (define_insn_and_split "*x86_64_shld_ndd_2" [(set (match_operand:DI 0 "register_operand") - (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand") - (match_operand:QI 3 "nonmemory_operand")) - (lshiftrt:DI (match_operand:DI 2 "register_operand") - (minus:QI (const_int 64) (match_dup 3))))) + (any_or_plus:DI + (ashift:DI (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "nonmemory_operand")) + (lshiftrt:DI (match_operand:DI 2 "register_operand") + (minus:QI (const_int 64) (match_dup 3))))) (clobber (reg:CC FLAGS_REG))] "TARGET_APX_NDD && ix86_pre_reload_split ()" @@ -16626,17 +16633,17 @@ (const_int 63)))) 0))) (clobber (reg:CC FLAGS_REG))])]) -(define_insn "x86_shld<nf_name>" +(define_insn "<aop_name_pfx>x86_shld<nf_name>" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") - (ior:SI (ashift:SI (match_dup 0) - (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic") - (const_int 31))) - (subreg:SI - (lshiftrt:DI - (zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (minus:QI (const_int 32) - (and:QI (match_dup 2) (const_int 31)))) 0)))] + (any_or_plus:SI + (ashift:SI (match_dup 0) + (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic") + (const_int 31))) + (subreg:SI + (lshiftrt:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (minus:QI (const_int 32) + (and:QI (match_dup 2) (const_int 31)))) 0)))] "<nf_condition>" "<nf_prefix>shld{l}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") @@ -16648,17 +16655,17 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shld_ndd<nf_name>" +(define_insn "<aop_name_pfx>x86_shld_ndd<nf_name>" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r") - (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") - (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic,Ic") - (const_int 31))) - (subreg:SI - (lshiftrt:DI - (zero_extend:DI - (match_operand:SI 2 "register_operand" "r,r")) - (minus:QI (const_int 32) - (and:QI (match_dup 3) (const_int 31)))) 0)))] + (any_or_plus:SI + (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") + (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic,Ic") + (const_int 31))) + (subreg:SI + (lshiftrt:DI + (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")) + (minus:QI (const_int 32) + (and:QI (match_dup 3) (const_int 31)))) 0)))] "TARGET_APX_NDD && <nf_condition>" "<nf_prefix>shld{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") @@ -16670,15 +16677,15 @@ (set_attr "mode" "SI")]) -(define_insn "x86_shld_1<nf_name>" +(define_insn "<aop_name_pfx>x86_shld_1<nf_name>" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") - (ior:SI (ashift:SI (match_dup 0) - (match_operand:QI 2 "const_0_to_31_operand")) - (subreg:SI - (lshiftrt:DI - (zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_63_operand")) 0)))] + (any_or_plus:SI + (ashift:SI (match_dup 0) + (match_operand:QI 2 "const_0_to_31_operand")) + (subreg:SI + (lshiftrt:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (match_operand:QI 3 "const_0_to_63_operand")) 0)))] "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) && <nf_condition>" "<nf_prefix>shld{l}\t{%2, %1, %0|%0, %1, %2}" @@ -16692,15 +16699,15 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shld_ndd_1<nf_name>" +(define_insn "<aop_name_pfx>x86_shld_ndd_1<nf_name>" [(set (match_operand:SI 0 "register_operand" "=r,r") - (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") - (match_operand:QI 3 "const_0_to_31_operand")) - (subreg:SI - (lshiftrt:DI - (zero_extend:DI - (match_operand:SI 2 "register_operand" "r,r")) - (match_operand:QI 4 "const_0_to_63_operand")) 0)))] + (any_or_plus:SI + (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") + (match_operand:QI 3 "const_0_to_31_operand")) + (subreg:SI + (lshiftrt:DI + (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")) + (match_operand:QI 4 "const_0_to_63_operand")) 0)))] "TARGET_APX_NDD && INTVAL (operands[4]) == 32 - INTVAL (operands[3]) && <nf_condition>" @@ -16716,11 +16723,11 @@ (define_insn_and_split "*x86_shld_shrd_1_nozext_nf" [(set (match_operand:SI 0 "nonimmediate_operand") - (ior:SI (ashift:SI (match_operand:SI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_31_operand")) - (lshiftrt:SI - (match_operand:SI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_31_operand"))))] + (any_or_plus:SI + (ashift:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand"))))] "TARGET_APX_NF && INTVAL (operands[3]) == 32 - INTVAL (operands[2]) && ix86_pre_reload_split ()" @@ -16771,11 +16778,11 @@ (define_insn_and_split "*x86_shld_shrd_1_nozext" [(set (match_operand:SI 0 "nonimmediate_operand") - (ior:SI (ashift:SI (match_operand:SI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_31_operand")) - (lshiftrt:SI - (match_operand:SI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_31_operand")))) + (any_or_plus:SI + (ashift:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand")))) (clobber (reg:CC FLAGS_REG))] "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) && ix86_pre_reload_split ()" @@ -16786,12 +16793,14 @@ if (rtx_equal_p (operands[4], operands[0])) { operands[1] = force_reg (SImode, operands[1]); - emit_insn (gen_x86_shld_1 (operands[0], operands[1], operands[2], operands[3])); + emit_insn (gen_x86_shld_1 (operands[0], operands[1], + operands[2], operands[3])); } else if (rtx_equal_p (operands[1], operands[0])) { operands[4] = force_reg (SImode, operands[4]); - emit_insn (gen_x86_shrd_1 (operands[0], operands[4], operands[3], operands[2])); + emit_insn (gen_x86_shrd_1 (operands[0], operands[4], + operands[3], operands[2])); } else if (TARGET_APX_NDD) { @@ -16810,24 +16819,25 @@ operands[2], operands[3])); emit_move_insn (operands[0], tmp); } - else - { - operands[1] = force_reg (SImode, operands[1]); - rtx tmp = gen_reg_rtx (SImode); - emit_move_insn (tmp, operands[4]); - emit_insn (gen_x86_shld_1 (tmp, operands[1], operands[2], operands[3])); - emit_move_insn (operands[0], tmp); - } - DONE; + else + { + operands[1] = force_reg (SImode, operands[1]); + rtx tmp = gen_reg_rtx (SImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_shld_1 (tmp, operands[1], operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; } [(set_attr "has_nf" "1")]) (define_insn_and_split "*x86_shld_2" [(set (match_operand:SI 0 "nonimmediate_operand") - (ior:SI (ashift:SI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand")) - (lshiftrt:SI (match_operand:SI 1 "register_operand") - (minus:QI (const_int 32) (match_dup 2))))) + (any_or_plus:SI + (ashift:SI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand")) + (lshiftrt:SI (match_operand:SI 1 "register_operand") + (minus:QI (const_int 32) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_pre_reload_split ()" "#" @@ -16845,10 +16855,11 @@ (define_insn_and_split "*x86_shld_ndd_2" [(set (match_operand:SI 0 "register_operand") - (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand") - (match_operand:QI 3 "nonmemory_operand")) - (lshiftrt:SI (match_operand:SI 2 "register_operand") - (minus:QI (const_int 32) (match_dup 3))))) + (any_or_plus:SI + (ashift:SI (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "nonmemory_operand")) + (lshiftrt:SI (match_operand:SI 2 "register_operand") + (minus:QI (const_int 32) (match_dup 3))))) (clobber (reg:CC FLAGS_REG))] "TARGET_APX_NDD && ix86_pre_reload_split ()" @@ -16871,7 +16882,7 @@ (match_dup 4)) (const_int 0))) (set (match_operand:SWI48 0 "register_operand") - (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0)) + (if_then_else:SWI48 (ne (reg:CCZ FLAGS_REG) (const_int 0)) (match_operand:SWI48 1 "register_operand") (match_dup 0))) (set (match_dup 1) @@ -17078,7 +17089,7 @@ (const_string "ishiftx") (eq_attr "alternative" "3,4") (const_string "ishift") - (and (match_test "TARGET_DOUBLE_WITH_ADD") + (and (match_test "TARGET_DOUBLE_WITH_ADD") (match_operand 2 "const1_operand")) (const_string "alu") ] @@ -17144,7 +17155,7 @@ (const_string "msklog") (eq_attr "alternative" "3,4") (const_string "ishift") - (and (and (match_test "TARGET_DOUBLE_WITH_ADD") + (and (and (match_test "TARGET_DOUBLE_WITH_ADD") (match_operand 0 "register_operand")) (match_operand 2 "const1_operand")) (const_string "alu") @@ -17202,7 +17213,7 @@ (const_string "msklog") (eq_attr "alternative" "4,5") (const_string "ishift") - (and (and (match_test "TARGET_DOUBLE_WITH_ADD") + (and (and (match_test "TARGET_DOUBLE_WITH_ADD") (match_operand 0 "register_operand")) (match_operand 2 "const1_operand")) (const_string "alu") @@ -17744,17 +17755,17 @@ } [(set_attr "has_nf" "1")]) -(define_insn "x86_64_shrd<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shrd<nf_name>" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") - (ior:DI (lshiftrt:DI (match_dup 0) - (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc") - (const_int 63))) - (subreg:DI - (ashift:TI - (zero_extend:TI - (match_operand:DI 1 "register_operand" "r")) - (minus:QI (const_int 64) - (and:QI (match_dup 2) (const_int 63)))) 0)))] + (any_or_plus:DI + (lshiftrt:DI (match_dup 0) + (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc") + (const_int 63))) + (subreg:DI + (ashift:TI + (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) + (minus:QI (const_int 64) + (and:QI (match_dup 2) (const_int 63)))) 0)))] "TARGET_64BIT && <nf_condition>" "<nf_prefix>shrd{q}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") @@ -17765,17 +17776,18 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shrd_ndd<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shrd_ndd<nf_name>" [(set (match_operand:DI 0 "register_operand" "=r,r") - (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "r,m") - (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc,Jc") - (const_int 63))) - (subreg:DI - (ashift:TI - (zero_extend:TI - (match_operand:DI 2 "register_operand" "r,r")) - (minus:QI (const_int 64) - (and:QI (match_dup 3) (const_int 63)))) 0)))] + (any_or_plus:DI + (lshiftrt:DI + (match_operand:DI 1 "nonimmediate_operand" "r,m") + (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc,Jc") + (const_int 63))) + (subreg:DI + (ashift:TI + (zero_extend:TI (match_operand:DI 2 "register_operand" "r,r")) + (minus:QI (const_int 64) + (and:QI (match_dup 3) (const_int 63)))) 0)))] "TARGET_APX_NDD && <nf_condition>" "<nf_prefix>shrd{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") @@ -17786,15 +17798,15 @@ (set_attr "has_nf" "1") (set_attr "mode" "DI")]) -(define_insn "x86_64_shrd_1<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shrd_1<nf_name>" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") - (ior:DI (lshiftrt:DI (match_dup 0) - (match_operand:QI 2 "const_0_to_63_operand")) - (subreg:DI - (ashift:TI - (zero_extend:TI - (match_operand:DI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_255_operand")) 0)))] + (any_or_plus:DI + (lshiftrt:DI (match_dup 0) + (match_operand:QI 2 "const_0_to_63_operand")) + (subreg:DI + (ashift:TI + (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) + (match_operand:QI 3 "const_0_to_255_operand")) 0)))] "TARGET_64BIT && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) && <nf_condition>" @@ -17808,15 +17820,15 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shrd_ndd_1<nf_name>" +(define_insn "<aop_name_pfx>x86_64_shrd_ndd_1<nf_name>" [(set (match_operand:DI 0 "register_operand" "=r,r") - (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "r,m") - (match_operand:QI 3 "const_0_to_63_operand")) - (subreg:DI - (ashift:TI - (zero_extend:TI - (match_operand:DI 2 "register_operand" "r,r")) - (match_operand:QI 4 "const_0_to_255_operand")) 0)))] + (any_or_plus:DI + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "r,m") + (match_operand:QI 3 "const_0_to_63_operand")) + (subreg:DI + (ashift:TI + (zero_extend:TI (match_operand:DI 2 "register_operand" "r,r")) + (match_operand:QI 4 "const_0_to_255_operand")) 0)))] "TARGET_APX_NDD && INTVAL (operands[4]) == 64 - INTVAL (operands[3]) && <nf_condition>" @@ -17832,11 +17844,11 @@ (define_insn_and_split "*x86_64_shrd_shld_1_nozext_nf" [(set (match_operand:DI 0 "nonimmediate_operand") - (ior:DI (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_63_operand")) - (ashift:DI - (match_operand:DI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_63_operand"))))] + (any_or_plus:DI + (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (ashift:DI (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand"))))] "TARGET_64BIT && TARGET_APX_NF && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) && ix86_pre_reload_split ()" @@ -17887,11 +17899,12 @@ (define_insn_and_split "*x86_64_shrd_shld_1_nozext" [(set (match_operand:DI 0 "nonimmediate_operand") - (ior:DI (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_63_operand")) - (ashift:DI - (match_operand:DI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_63_operand")))) + (any_or_plus:DI + (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (ashift:DI + (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) @@ -17908,24 +17921,25 @@ else if (rtx_equal_p (operands[1], operands[0])) { operands[4] = force_reg (DImode, operands[4]); - emit_insn (gen_x86_64_shld_1 (operands[0], operands[4], operands[3], operands[2])); + emit_insn (gen_x86_64_shld_1 (operands[0], operands[4], + operands[3], operands[2])); } else if (TARGET_APX_NDD) { rtx tmp = gen_reg_rtx (DImode); if (MEM_P (operands[4])) - { + { operands[1] = force_reg (DImode, operands[1]); emit_insn (gen_x86_64_shrd_ndd_1 (tmp, operands[4], operands[1], operands[2], operands[3])); - } - else if (MEM_P (operands[1])) - emit_insn (gen_x86_64_shld_ndd_1 (tmp, operands[1], operands[4], - operands[3], operands[2])); - else - emit_insn (gen_x86_64_shrd_ndd_1 (tmp, operands[4], operands[1], - operands[2], operands[3])); - emit_move_insn (operands[0], tmp); + } + else if (MEM_P (operands[1])) + emit_insn (gen_x86_64_shld_ndd_1 (tmp, operands[1], operands[4], + operands[3], operands[2])); + else + emit_insn (gen_x86_64_shrd_ndd_1 (tmp, operands[4], operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); } else { @@ -17941,10 +17955,11 @@ (define_insn_and_split "*x86_64_shrd_2" [(set (match_operand:DI 0 "nonimmediate_operand") - (ior:DI (lshiftrt:DI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand")) - (ashift:DI (match_operand:DI 1 "register_operand") - (minus:QI (const_int 64) (match_dup 2))))) + (any_or_plus:DI + (lshiftrt:DI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand")) + (ashift:DI (match_operand:DI 1 "register_operand") + (minus:QI (const_int 64) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_pre_reload_split ()" "#" @@ -17962,10 +17977,11 @@ (define_insn_and_split "*x86_64_shrd_ndd_2" [(set (match_operand:DI 0 "register_operand") - (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand") - (match_operand:QI 3 "nonmemory_operand")) - (ashift:DI (match_operand:DI 2 "register_operand") - (minus:QI (const_int 64) (match_dup 2))))) + (any_or_plus:DI + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "nonmemory_operand")) + (ashift:DI (match_operand:DI 2 "register_operand") + (minus:QI (const_int 64) (match_dup 3))))) (clobber (reg:CC FLAGS_REG))] "TARGET_APX_NDD && ix86_pre_reload_split ()" @@ -17982,17 +17998,17 @@ (const_int 63)))) 0))) (clobber (reg:CC FLAGS_REG))])]) -(define_insn "x86_shrd<nf_name>" +(define_insn "<aop_name_pfx>x86_shrd<nf_name>" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") - (ior:SI (lshiftrt:SI (match_dup 0) - (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic") - (const_int 31))) - (subreg:SI - (ashift:DI - (zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (minus:QI (const_int 32) - (and:QI (match_dup 2) (const_int 31)))) 0)))] + (any_or_plus:SI + (lshiftrt:SI (match_dup 0) + (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic") + (const_int 31))) + (subreg:SI + (ashift:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (minus:QI (const_int 32) + (and:QI (match_dup 2) (const_int 31)))) 0)))] "<nf_condition>" "<nf_prefix>shrd{l}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") @@ -18004,17 +18020,17 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shrd_ndd<nf_name>" +(define_insn "<aop_name_pfx>x86_shrd_ndd<nf_name>" [(set (match_operand:SI 0 "register_operand" "=r,r") - (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") - (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic,Ic") - (const_int 31))) - (subreg:SI - (ashift:DI - (zero_extend:DI - (match_operand:SI 2 "register_operand" "r,r")) - (minus:QI (const_int 32) - (and:QI (match_dup 3) (const_int 31)))) 0)))] + (any_or_plus:SI + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") + (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic,Ic") + (const_int 31))) + (subreg:SI + (ashift:DI + (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")) + (minus:QI (const_int 32) + (and:QI (match_dup 3) (const_int 31)))) 0)))] "TARGET_APX_NDD && <nf_condition>" "<nf_prefix>shrd{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") @@ -18025,15 +18041,15 @@ (set_attr "has_nf" "1") (set_attr "mode" "SI")]) -(define_insn "x86_shrd_1<nf_name>" +(define_insn "<aop_name_pfx>x86_shrd_1<nf_name>" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") - (ior:SI (lshiftrt:SI (match_dup 0) - (match_operand:QI 2 "const_0_to_31_operand")) - (subreg:SI - (ashift:DI - (zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_63_operand")) 0)))] + (any_or_plus:SI + (lshiftrt:SI (match_dup 0) + (match_operand:QI 2 "const_0_to_31_operand")) + (subreg:SI + (ashift:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (match_operand:QI 3 "const_0_to_63_operand")) 0)))] "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) && <nf_condition>" "<nf_prefix>shrd{l}\t{%2, %1, %0|%0, %1, %2}" @@ -18047,15 +18063,15 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shrd_ndd_1<nf_name>" +(define_insn "<aop_name_pfx>x86_shrd_ndd_1<nf_name>" [(set (match_operand:SI 0 "register_operand" "=r,r") - (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") - (match_operand:QI 3 "const_0_to_31_operand")) - (subreg:SI - (ashift:DI - (zero_extend:DI - (match_operand:SI 2 "register_operand" "r,r")) - (match_operand:QI 4 "const_0_to_63_operand")) 0)))] + (any_or_plus:SI + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "r,m") + (match_operand:QI 3 "const_0_to_31_operand")) + (subreg:SI + (ashift:DI + (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")) + (match_operand:QI 4 "const_0_to_63_operand")) 0)))] "TARGET_APX_NDD && (INTVAL (operands[4]) == 32 - INTVAL (operands[3])) && <nf_condition>" @@ -18071,11 +18087,11 @@ (define_insn_and_split "*x86_shrd_shld_1_nozext_nf" [(set (match_operand:SI 0 "nonimmediate_operand") - (ior:SI (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_31_operand")) - (ashift:SI - (match_operand:SI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_31_operand"))))] + (any_or_plus:SI + (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (ashift:SI (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand"))))] "TARGET_APX_NF && INTVAL (operands[3]) == 32 - INTVAL (operands[2]) && ix86_pre_reload_split ()" @@ -18126,11 +18142,11 @@ (define_insn_and_split "*x86_shrd_shld_1_nozext" [(set (match_operand:SI 0 "nonimmediate_operand") - (ior:SI (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand") - (match_operand:QI 2 "const_0_to_31_operand")) - (ashift:SI - (match_operand:SI 1 "nonimmediate_operand") - (match_operand:QI 3 "const_0_to_31_operand")))) + (any_or_plus:SI + (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (ashift:SI (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand")))) (clobber (reg:CC FLAGS_REG))] "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) && ix86_pre_reload_split ()" @@ -18146,43 +18162,45 @@ else if (rtx_equal_p (operands[1], operands[0])) { operands[4] = force_reg (SImode, operands[4]); - emit_insn (gen_x86_shld_1 (operands[0], operands[4], operands[3], operands[2])); + emit_insn (gen_x86_shld_1 (operands[0], operands[4], + operands[3], operands[2])); } else if (TARGET_APX_NDD) { rtx tmp = gen_reg_rtx (SImode); if (MEM_P (operands[4])) - { + { operands[1] = force_reg (SImode, operands[1]); emit_insn (gen_x86_shrd_ndd_1 (tmp, operands[4], operands[1], operands[2], operands[3])); - } + } else if (MEM_P (operands[1])) - emit_insn (gen_x86_shld_ndd_1 (tmp, operands[1], operands[4], + emit_insn (gen_x86_shld_ndd_1 (tmp, operands[1], operands[4], operands[3], operands[2])); else - emit_insn (gen_x86_shrd_ndd_1 (tmp, operands[4], operands[1], + emit_insn (gen_x86_shrd_ndd_1 (tmp, operands[4], operands[1], operands[2], operands[3])); emit_move_insn (operands[0], tmp); - } - else - { - operands[1] = force_reg (SImode, operands[1]); - rtx tmp = gen_reg_rtx (SImode); - emit_move_insn (tmp, operands[4]); - emit_insn (gen_x86_shrd_1 (tmp, operands[1], operands[2], operands[3])); - emit_move_insn (operands[0], tmp); - } - DONE; + } + else + { + operands[1] = force_reg (SImode, operands[1]); + rtx tmp = gen_reg_rtx (SImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_shrd_1 (tmp, operands[1], operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; } [(set_attr "has_nf" "1")]) (define_insn_and_split "*x86_shrd_2" [(set (match_operand:SI 0 "nonimmediate_operand") - (ior:SI (lshiftrt:SI (match_dup 0) - (match_operand:QI 2 "nonmemory_operand")) - (ashift:SI (match_operand:SI 1 "register_operand") - (minus:QI (const_int 32) (match_dup 2))))) + (any_or_plus:SI + (lshiftrt:SI (match_dup 0) + (match_operand:QI 2 "nonmemory_operand")) + (ashift:SI (match_operand:SI 1 "register_operand") + (minus:QI (const_int 32) (match_dup 2))))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_pre_reload_split ()" "#" @@ -18200,10 +18218,11 @@ (define_insn_and_split "*x86_shrd_ndd_2" [(set (match_operand:SI 0 "register_operand") - (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand") - (match_operand:QI 3 "nonmemory_operand")) - (ashift:SI (match_operand:SI 2 "register_operand") - (minus:QI (const_int 32) (match_dup 3))))) + (any_or_plus:SI + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "nonmemory_operand")) + (ashift:SI (match_operand:SI 2 "register_operand") + (minus:QI (const_int 32) (match_dup 3))))) (clobber (reg:CC FLAGS_REG))] "TARGET_APX_NDD && ix86_pre_reload_split ()" @@ -18211,7 +18230,7 @@ "&& 1" [(parallel [(set (match_dup 0) (ior:SI (lshiftrt:SI (match_dup 1) - (and:QI (match_dup 3) (const_int 31))) + (and:QI (match_dup 3) (const_int 31))) (subreg:SI (ashift:DI (zero_extend:DI (match_dup 2)) @@ -18350,7 +18369,7 @@ ;; highpart of a DI to be extracted, but allowing it to be clobbered. (define_insn_and_split "*highpartdisi2" [(set (subreg:DI (match_operand:SI 0 "register_operand" "=r,x,?k,r,r") 0) - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0,k,r,m") + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0,k,r,m") (const_int 32))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 80761b0a8a62..648c12f6e7b9 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -7272,6 +7272,22 @@ mode; for example, if @var{n} is @code{HImode}, a CRC16 is calculated. @item @samp{crc_rev@var{m}@var{n}4} Similar to @samp{crc@var{m}@var{n}4}, but calculates a bit-reversed CRC. +@mdindex aop@var{m}3 +@item @samp{aop@var{m}3} +Like @samp{add@var{m}3} or @samp{ior@var{m}3}, perform a bit-wise +addition between operand 1 and operand 2, which are known to have +no set bits in common, and store the result in operand 0. Because +the input operands are bit-wise disjoint, the same result is obtained +for @code{IOR}, @code{XOR} and @code{PLUS}, so this @code{aop} (``any or +plus'') pattern allows the target to select the most suitable representation. +For modes wider than a word, on targets without add with carry, +@code{IOR} may be more efficient than @code{PLUS}. On targets with +shift-and-add (such as x86's @code{lea}) or multiply-add (@code{fma@var{m}4}) +instructions, @code{PLUS} may produce more efficent code than @code{IOR}. +If the machine description doesn't specify this pattern, the middle-end +will by default use @code{PLUS} for @code{SImode} and @code{word_mode}, +and @code{IOR} otherwise. + @end table @node Standard Pattern Names for Vectorization
