diff options
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 318 |
1 files changed, 227 insertions, 91 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1bb96fd07db..198b59d2e47 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -759,77 +759,183 @@ (include "constraints.md") -;; Compare instructions. +;; Compare and branch/compare and store instructions. -;; All compare insns have expanders that save the operands away without -;; actually generating RTL. The bCOND or sCOND (emitted immediately -;; after the cmp) will actually emit the cmpM. +(define_expand "cbranchti4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:TI 1 "nonimmediate_operand" "") + (match_operand:TI 2 "x86_64_general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_64BIT" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (TImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) -(define_expand "cmpti" +(define_expand "cbranchdi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:TI 0 "nonimmediate_operand" "") - (match_operand:TI 1 "x86_64_general_operand" "")))] + (compare:CC (match_operand:DI 1 "nonimmediate_operand" "") + (match_operand:DI 2 "x86_64_general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (DImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstoredi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:DI 2 "nonimmediate_operand" "") + (match_operand:DI 3 "x86_64_general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_64BIT" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (TImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (DImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmpdi" +(define_expand "cbranchsi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "x86_64_general_operand" "")))] + (compare:CC (match_operand:SI 1 "cmpsi_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (DImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (SImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpsi" +(define_expand "cstoresi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 0 "cmpsi_operand" "") - (match_operand:SI 1 "general_operand" "")))] + (compare:CC (match_operand:SI 2 "cmpsi_operand" "") + (match_operand:SI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (SImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (SImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmphi" +(define_expand "cbranchhi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" "")))] + (compare:CC (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (HImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (HImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpqi" +(define_expand "cstorehi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")))] - "TARGET_QIMODE_MATH" + (compare:CC (match_operand:HI 2 "nonimmediate_operand" "") + (match_operand:HI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (QImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (HImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + + +(define_expand "cbranchqi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:QI 1 "nonimmediate_operand" "") + (match_operand:QI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (QImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + + +(define_expand "cstoreqi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:QI 2 "nonimmediate_operand" "") + (match_operand:QI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "" +{ + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (QImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) + (define_insn "cmpdi_ccno_1_rex64" [(set (reg FLAGS_REG) (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr") @@ -1078,39 +1184,103 @@ ;; which would allow mix and match FP modes on the compares. Which is what ;; the old patterns did, but with many more of them. -(define_expand "cmpxf" +(define_expand "cbranchxf4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:XF 1 "nonmemory_operand" "") + (match_operand:XF 2 "nonmemory_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_80387" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorexf4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:XF 0 "nonmemory_operand" "") - (match_operand:XF 1 "nonmemory_operand" "")))] + (compare:CC (match_operand:XF 2 "nonmemory_operand" "") + (match_operand:XF 3 "nonmemory_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_80387" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmp<mode>" +(define_expand "cbranch<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:MODEF 0 "cmp_fp_expander_operand" "") - (match_operand:MODEF 1 "cmp_fp_expander_operand" "")))] + (compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "") + (match_operand:MODEF 2 "cmp_fp_expander_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpcc" +(define_expand "cstore<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand 0 "flags_reg_operand" "") - (match_operand 1 "general_operand" "")))] + (compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "") + (match_operand:MODEF 3 "cmp_fp_expander_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" +{ + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(match_operand 1 "flags_reg_operand" "") + (match_operand 2 "const0_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorecc4" + [(set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(match_operand 2 "flags_reg_operand" "") + (match_operand 3 "const0_operand" "")]))] "" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) + ;; FP compares, step 1: ;; Set the FP condition codes. ;; @@ -14182,18 +14352,6 @@ ;; to avoid partial register stalls. Otherwise do things the setcc+movzx ;; way, which can later delete the movzx if only QImode is needed. -(define_expand "s<code>" - [(set (match_operand:QI 0 "register_operand" "") - (int_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;") - -(define_expand "s<code>" - [(set (match_operand:QI 0 "register_operand" "") - (fp_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;") - (define_insn "*setcc_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (match_operator:QI 1 "ix86_comparison_operator" @@ -14322,27 +14480,6 @@ ;; Basic conditional jump instructions. ;; We ignore the overflow flag for signed branch instructions. -;; For all bCOND expanders, also expand the compare or test insn that -;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'. - -(define_expand "b<code>" - [(set (pc) - (if_then_else (int_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "ix86_expand_branch (<CODE>, operands[0]); DONE;") - -(define_expand "b<code>" - [(set (pc) - (if_then_else (fp_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (<CODE>, operands[0]); DONE;") - (define_insn "*jcc_1" [(set (pc) (if_then_else (match_operator 1 "ix86_comparison_operator" @@ -22004,9 +22141,8 @@ emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1])); #endif - ix86_compare_op0 = flags; - ix86_compare_op1 = const0_rtx; - emit_jump_insn (gen_beq (operands[2])); + emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx), + flags, const0_rtx, operands[2])); DONE; }) |