diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 694 |
1 files changed, 291 insertions, 403 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 9df70cf3eaf..8c51a129b98 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -1422,16 +1422,14 @@ rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1])) ? operands[0] : gen_reg_rtx (SImode)); - HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff; - HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff); - - if (low & 0x8000) - high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16; + HOST_WIDE_INT val = INTVAL (operands[2]); + HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); + HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode); /* The ordering here is important for the prolog expander. When space is allocated from the stack, adding 'low' first may produce a temporary deallocation (which would be bad). */ - emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (high))); + emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (rest))); emit_insn (gen_addsi3 (operands[0], tmp, GEN_INT (low))); DONE; } @@ -1525,13 +1523,11 @@ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] " { - HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff; - HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff); - - if (low & 0x8000) - high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16; + HOST_WIDE_INT val = INTVAL (operands[2]); + HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); + HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode); - operands[3] = GEN_INT (high); + operands[3] = GEN_INT (rest); operands[4] = GEN_INT (low); }") @@ -2263,6 +2259,7 @@ " { if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0) ; else if (TARGET_POWERPC) @@ -2314,12 +2311,9 @@ rtx temp1; rtx temp2; - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; - - i = exact_log2 (INTVAL (operands[2])); - - if (i < 0) + if (GET_CODE (operands[2]) != CONST_INT + || INTVAL (operands[2]) < 0 + || (i = exact_log2 (INTVAL (operands[2]))) < 0) FAIL; temp1 = gen_reg_rtx (SImode); @@ -2335,7 +2329,7 @@ [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (div:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "const_int_operand" "N")))] - "exact_log2 (INTVAL (operands[2])) >= 0" + "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0" "{srai|srawi} %0,%1,%p2\;{aze|addze} %0,%0" [(set_attr "length" "8")]) @@ -2345,7 +2339,7 @@ (match_operand:SI 2 "const_int_operand" "N,N")) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r"))] - "exact_log2 (INTVAL (operands[2])) >= 0" + "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0" "@ {srai|srawi} %3,%1,%p2\;{aze.|addze.} %3,%3 #" @@ -2358,7 +2352,8 @@ (match_operand:SI 2 "const_int_operand" "")) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed" + "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0 + && reload_completed" [(set (match_dup 3) (div:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) @@ -2373,7 +2368,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (div:SI (match_dup 1) (match_dup 2)))] - "exact_log2 (INTVAL (operands[2])) >= 0" + "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0" "@ {srai|srawi} %0,%1,%p2\;{aze.|addze.} %0,%0 #" @@ -2387,7 +2382,8 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (div:SI (match_dup 1) (match_dup 2)))] - "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed" + "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0 + && reload_completed" [(set (match_dup 0) (div:SI (match_dup 1) (match_dup 2))) (set (match_dup 3) @@ -4808,60 +4804,35 @@ ;; single DEFINE_INSN for fsel and the define_splits to make them if made by ;; combine. (define_expand "maxsf3" - [(set (match_dup 3) - (minus:SF (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" ""))) - (set (match_operand:SF 0 "gpc_reg_operand" "") - (if_then_else:SF (ge (match_dup 3) - (const_int 0)) - (match_dup 1) - (match_dup 2)))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - " -{ operands[3] = gen_reg_rtx (SFmode); }") - -(define_split [(set (match_operand:SF 0 "gpc_reg_operand" "") - (smax:SF (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" ""))) - (clobber (match_operand:SF 3 "gpc_reg_operand" ""))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - [(set (match_dup 3) - (minus:SF (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (if_then_else:SF (ge (match_dup 3) - (const_int 0)) + (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "") + (match_operand:SF 2 "gpc_reg_operand" "")) (match_dup 1) (match_dup 2)))] - "") + "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" + "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}") (define_expand "minsf3" - [(set (match_dup 3) - (minus:SF (match_operand:SF 2 "gpc_reg_operand" "") - (match_operand:SF 1 "gpc_reg_operand" ""))) - (set (match_operand:SF 0 "gpc_reg_operand" "") - (if_then_else:SF (ge (match_dup 3) - (const_int 0)) - (match_dup 1) - (match_dup 2)))] + [(set (match_operand:SF 0 "gpc_reg_operand" "") + (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "") + (match_operand:SF 2 "gpc_reg_operand" "")) + (match_dup 2) + (match_dup 1)))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - " -{ operands[3] = gen_reg_rtx (SFmode); }") + "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}") (define_split [(set (match_operand:SF 0 "gpc_reg_operand" "") - (smin:SF (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" ""))) - (clobber (match_operand:SF 3 "gpc_reg_operand" ""))] + (match_operator:SF 3 "min_max_operator" + [(match_operand:SF 1 "gpc_reg_operand" "") + (match_operand:SF 2 "gpc_reg_operand" "")]))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - [(set (match_dup 3) - (minus:SF (match_dup 2) (match_dup 1))) - (set (match_dup 0) - (if_then_else:SF (ge (match_dup 3) - (const_int 0)) - (match_dup 1) - (match_dup 2)))] - "") + [(const_int 0)] + " +{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), + operands[1], operands[2]); + DONE; +}") (define_expand "movsfcc" [(set (match_operand:SF 0 "gpc_reg_operand" "") @@ -4871,82 +4842,26 @@ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" " { - rtx temp, op0, op1; - enum rtx_code code = GET_CODE (operands[1]); - if (! rs6000_compare_fp_p) - FAIL; - switch (code) - { - case GE: case EQ: case NE: - op0 = rs6000_compare_op0; - op1 = rs6000_compare_op1; - break; - case GT: - op0 = rs6000_compare_op1; - op1 = rs6000_compare_op0; - temp = operands[2]; operands[2] = operands[3]; operands[3] = temp; - break; - case LE: - op0 = rs6000_compare_op1; - op1 = rs6000_compare_op0; - break; - case LT: - op0 = rs6000_compare_op0; - op1 = rs6000_compare_op1; - temp = operands[2]; operands[2] = operands[3]; operands[3] = temp; - break; - default: - FAIL; - } - if (GET_MODE (rs6000_compare_op0) == DFmode) - { - temp = gen_reg_rtx (DFmode); - emit_insn (gen_subdf3 (temp, op0, op1)); - emit_insn (gen_fseldfsf4 (operands[0], temp, operands[2], operands[3])); - if (code == EQ) - { - emit_insn (gen_negdf2 (temp, temp)); - emit_insn (gen_fseldfsf4 (operands[0], temp, operands[0], operands[3])); - } - else if (code == NE) - { - emit_insn (gen_negdf2 (temp, temp)); - emit_insn (gen_fseldfsf4 (operands[0], temp, operands[3], operands[0])); - } - } + if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) + DONE; else - { - temp = gen_reg_rtx (SFmode); - emit_insn (gen_subsf3 (temp, op0, op1)); - emit_insn (gen_fselsfsf4 (operands[0], temp, operands[2], operands[3])); - if (code == EQ) - { - emit_insn (gen_negsf2 (temp, temp)); - emit_insn (gen_fselsfsf4 (operands[0], temp, operands[0], operands[3])); - } - else if (code == NE) - { - emit_insn (gen_negsf2 (temp, temp)); - emit_insn (gen_fselsfsf4 (operands[0], temp, operands[3], operands[0])); - } - } - DONE; + FAIL; }") -(define_insn "fselsfsf4" +(define_insn "*fselsfsf4" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "f") - (const_int 0)) + (match_operand:SF 4 "zero_fp_constant" "F")) (match_operand:SF 2 "gpc_reg_operand" "f") (match_operand:SF 3 "gpc_reg_operand" "f")))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" "fsel %0,%1,%2,%3" [(set_attr "type" "fp")]) -(define_insn "fseldfsf4" +(define_insn "*fseldfsf4" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "f") - (const_int 0)) + (match_operand:DF 4 "zero_fp_constant" "F")) (match_operand:SF 2 "gpc_reg_operand" "f") (match_operand:SF 3 "gpc_reg_operand" "f")))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" @@ -5049,66 +4964,39 @@ "fsqrt %0,%1" [(set_attr "type" "dsqrt")]) -;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a -;; fsel instruction and some auxiliary computations. Then we just have a -;; single DEFINE_INSN for fsel and the define_splits to make them if made by -;; combine. +;; The conditional move instructions allow us to perform max and min +;; operations even when (define_expand "maxdf3" - [(set (match_dup 3) - (minus:DF (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" ""))) - (set (match_operand:DF 0 "gpc_reg_operand" "") - (if_then_else:DF (ge (match_dup 3) - (const_int 0)) - (match_dup 1) - (match_dup 2)))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - " -{ operands[3] = gen_reg_rtx (DFmode); }") - -(define_split [(set (match_operand:DF 0 "gpc_reg_operand" "") - (smax:DF (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" ""))) - (clobber (match_operand:DF 3 "gpc_reg_operand" ""))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - [(set (match_dup 3) - (minus:DF (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (if_then_else:DF (ge (match_dup 3) - (const_int 0)) + (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "") + (match_operand:DF 2 "gpc_reg_operand" "")) (match_dup 1) (match_dup 2)))] - "") + "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" + "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}") (define_expand "mindf3" - [(set (match_dup 3) - (minus:DF (match_operand:DF 2 "gpc_reg_operand" "") - (match_operand:DF 1 "gpc_reg_operand" ""))) - (set (match_operand:DF 0 "gpc_reg_operand" "") - (if_then_else:DF (ge (match_dup 3) - (const_int 0)) - (match_dup 1) - (match_dup 2)))] + [(set (match_operand:DF 0 "gpc_reg_operand" "") + (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "") + (match_operand:DF 2 "gpc_reg_operand" "")) + (match_dup 2) + (match_dup 1)))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - " -{ operands[3] = gen_reg_rtx (DFmode); }") + "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}") (define_split [(set (match_operand:DF 0 "gpc_reg_operand" "") - (smin:DF (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" ""))) - (clobber (match_operand:DF 3 "gpc_reg_operand" ""))] + (match_operator:DF 3 "min_max_operator" + [(match_operand:DF 1 "gpc_reg_operand" "") + (match_operand:DF 2 "gpc_reg_operand" "")]))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" - [(set (match_dup 3) - (minus:DF (match_dup 2) (match_dup 1))) - (set (match_dup 0) - (if_then_else:DF (ge (match_dup 3) - (const_int 0)) - (match_dup 1) - (match_dup 2)))] - "") + [(const_int 0)] + " +{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), + operands[1], operands[2]); + DONE; +}") (define_expand "movdfcc" [(set (match_operand:DF 0 "gpc_reg_operand" "") @@ -5118,82 +5006,26 @@ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" " { - rtx temp, op0, op1; - enum rtx_code code = GET_CODE (operands[1]); - if (! rs6000_compare_fp_p) - FAIL; - switch (code) - { - case GE: case EQ: case NE: - op0 = rs6000_compare_op0; - op1 = rs6000_compare_op1; - break; - case GT: - op0 = rs6000_compare_op1; - op1 = rs6000_compare_op0; - temp = operands[2]; operands[2] = operands[3]; operands[3] = temp; - break; - case LE: - op0 = rs6000_compare_op1; - op1 = rs6000_compare_op0; - break; - case LT: - op0 = rs6000_compare_op0; - op1 = rs6000_compare_op1; - temp = operands[2]; operands[2] = operands[3]; operands[3] = temp; - break; - default: - FAIL; - } - if (GET_MODE (rs6000_compare_op0) == DFmode) - { - temp = gen_reg_rtx (DFmode); - emit_insn (gen_subdf3 (temp, op0, op1)); - emit_insn (gen_fseldfdf4 (operands[0], temp, operands[2], operands[3])); - if (code == EQ) - { - emit_insn (gen_negdf2 (temp, temp)); - emit_insn (gen_fseldfdf4 (operands[0], temp, operands[0], operands[3])); - } - else if (code == NE) - { - emit_insn (gen_negdf2 (temp, temp)); - emit_insn (gen_fseldfdf4 (operands[0], temp, operands[3], operands[0])); - } - } + if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) + DONE; else - { - temp = gen_reg_rtx (SFmode); - emit_insn (gen_subsf3 (temp, op0, op1)); - emit_insn (gen_fselsfdf4 (operands[0], temp, operands[2], operands[3])); - if (code == EQ) - { - emit_insn (gen_negsf2 (temp, temp)); - emit_insn (gen_fselsfdf4 (operands[0], temp, operands[0], operands[3])); - } - else if (code == NE) - { - emit_insn (gen_negsf2 (temp, temp)); - emit_insn (gen_fselsfdf4 (operands[0], temp, operands[3], operands[0])); - } - } - DONE; + FAIL; }") -(define_insn "fseldfdf4" +(define_insn "*fseldfdf4" [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "f") - (const_int 0)) + (match_operand:DF 4 "zero_fp_constant" "F")) (match_operand:DF 2 "gpc_reg_operand" "f") (match_operand:DF 3 "gpc_reg_operand" "f")))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT" "fsel %0,%1,%2,%3" [(set_attr "type" "fp")]) -(define_insn "fselsfdf4" +(define_insn "*fselsfdf4" [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f") - (const_int 0)) + (match_operand:SF 4 "zero_fp_constant" "F")) (match_operand:DF 2 "gpc_reg_operand" "f") (match_operand:DF 3 "gpc_reg_operand" "f")))] "TARGET_PPC_GFXOPT" @@ -5739,7 +5571,7 @@ (define_expand "adddi3" [(set (match_operand:DI 0 "gpc_reg_operand" "") (plus:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:DI 2 "reg_or_arith_cint_operand" "")))] + (match_operand:DI 2 "reg_or_add_cint64_operand" "")))] "" " { @@ -5755,13 +5587,17 @@ rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1])) ? operands[0] : gen_reg_rtx (DImode)); - HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff; - HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff); + HOST_WIDE_INT val = INTVAL (operands[2]); + HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); + HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode); - if (low & 0x8000) - high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16; + if (!CONST_OK_FOR_LETTER_P (rest, 'L')) + FAIL; - emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (high))); + /* The ordering here is important for the prolog expander. + When space is allocated from the stack, adding 'low' first may + produce a temporary deallocation (which would be bad). */ + emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (rest))); emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low))); DONE; } @@ -5854,14 +5690,22 @@ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] " { - HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff; - HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff); + HOST_WIDE_INT val = INTVAL (operands[2]); + HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); + HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode); - if (low & 0x8000) - high+=0x10000, low |= ((HOST_WIDE_INT) -1) << 16; - - operands[3] = GEN_INT (high); operands[4] = GEN_INT (low); + if (CONST_OK_FOR_LETTER_P (rest, 'L')) + operands[3] = GEN_INT (rest); + else if (! no_new_pseudos) + { + operands[3] = gen_reg_rtx (DImode); + emit_move_insn (operands[3], operands[2]); + emit_insn (gen_adddi3 (operands[0], operands[1], operands[3])); + DONE; + } + else + FAIL; }") (define_insn "one_cmpldi2" @@ -5990,7 +5834,7 @@ (define_expand "subdi3" [(set (match_operand:DI 0 "gpc_reg_operand" "") (minus:DI (match_operand:DI 1 "reg_or_short_operand" "") - (match_operand:DI 2 "reg_or_arith_cint_operand" "")))] + (match_operand:DI 2 "reg_or_sub_cint64_operand" "")))] "" " { @@ -6149,6 +5993,7 @@ " { if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0) ; else @@ -6162,11 +6007,13 @@ "TARGET_POWERPC64" " { - int i = exact_log2 (INTVAL (operands[2])); + int i; rtx temp1; rtx temp2; - if (GET_CODE (operands[2]) != CONST_INT || i < 0) + if (GET_CODE (operands[2]) != CONST_INT + || INTVAL (operands[2]) <= 0 + || (i = exact_log2 (INTVAL (operands[2]))) < 0) FAIL; temp1 = gen_reg_rtx (DImode); @@ -6182,7 +6029,8 @@ [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (div:DI (match_operand:DI 1 "gpc_reg_operand" "r") (match_operand:DI 2 "const_int_operand" "N")))] - "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0" + "TARGET_POWERPC64 && INTVAL (operands[2]) > 0 + && exact_log2 (INTVAL (operands[2])) >= 0" "sradi %0,%1,%p2\;addze %0,%0" [(set_attr "length" "8")]) @@ -6192,7 +6040,8 @@ (match_operand:DI 2 "const_int_operand" "N,N")) (const_int 0))) (clobber (match_scratch:DI 3 "=r,r"))] - "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0" + "TARGET_POWERPC64 && INTVAL (operands[2]) > 0 + && exact_log2 (INTVAL (operands[2])) >= 0" "@ sradi %3,%1,%p2\;addze. %3,%3 #" @@ -6205,7 +6054,8 @@ (match_operand:DI 2 "const_int_operand" "")) (const_int 0))) (clobber (match_scratch:DI 3 ""))] - "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed" + "TARGET_POWERPC64 && INTVAL (operands[2]) > 0 + && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed" [(set (match_dup 3) (div:DI (match_dup 1) (match_dup 2))) (set (match_dup 0) @@ -6220,7 +6070,8 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (div:DI (match_dup 1) (match_dup 2)))] - "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0" + "TARGET_POWERPC64 && INTVAL (operands[2]) > 0 + && exact_log2 (INTVAL (operands[2])) >= 0" "@ sradi %0,%1,%p2\;addze. %0,%0 #" @@ -6234,7 +6085,8 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") (div:DI (match_dup 1) (match_dup 2)))] - "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed" + "TARGET_POWERPC64 && INTVAL (operands[2]) > 0 + && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed" [(set (match_dup 0) (div:DI (match_dup 1) (match_dup 2))) (set (match_dup 3) @@ -6706,8 +6558,8 @@ [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "const_int_operand" "i")) - (match_operand:DI 3 "rldic_operand" "n")))] - "includes_lshift64_p (operands[2], operands[3])" + (match_operand:DI 3 "const_int_operand" "n")))] + "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])" "rldic %0,%1,%H2,%W3") (define_insn "ashldi3_internal5" @@ -6715,10 +6567,10 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") (match_operand:SI 2 "const_int_operand" "i,i")) - (match_operand:DI 3 "rldic_operand" "n,n")) + (match_operand:DI 3 "const_int_operand" "n,n")) (const_int 0))) (clobber (match_scratch:DI 4 "=r,r"))] - "includes_lshift64_p (operands[2], operands[3])" + "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])" "@ rldic. %4,%1,%H2,%W3 #" @@ -6730,10 +6582,11 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "") (match_operand:SI 2 "const_int_operand" "")) - (match_operand:DI 3 "rldic_operand" "")) + (match_operand:DI 3 "const_int_operand" "")) (const_int 0))) (clobber (match_scratch:DI 4 ""))] - "includes_lshift64_p (operands[2], operands[3]) && reload_completed" + "TARGET_POWERPC64 && reload_completed + && includes_rldic_lshift_p (operands[2], operands[3])" [(set (match_dup 4) (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3))) @@ -6747,11 +6600,11 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") (match_operand:SI 2 "const_int_operand" "i,i")) - (match_operand:DI 3 "rldic_operand" "n,n")) + (match_operand:DI 3 "const_int_operand" "n,n")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] - "includes_lshift64_p (operands[2], operands[3])" + "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])" "@ rldic. %0,%1,%H2,%W3 #" @@ -6763,11 +6616,88 @@ (compare:CC (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "") (match_operand:SI 2 "const_int_operand" "")) - (match_operand:DI 3 "rldic_operand" "")) + (match_operand:DI 3 "const_int_operand" "")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] - "includes_lshift64_p (operands[2], operands[3]) && reload_completed" + "TARGET_POWERPC64 && reload_completed + && includes_rldic_lshift_p (operands[2], operands[3])" + [(set (match_dup 0) + (and:DI (ashift:DI (match_dup 1) (match_dup 2)) + (match_dup 3))) + (set (match_dup 4) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + +(define_insn "*ashldi3_internal7" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r") + (match_operand:SI 2 "const_int_operand" "i")) + (match_operand:DI 3 "mask64_operand" "S")))] + "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])" + "rldicr %0,%1,%H2,%S3") + +(define_insn "ashldi3_internal8" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") + (compare:CC + (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "const_int_operand" "i,i")) + (match_operand:DI 3 "mask64_operand" "S,S")) + (const_int 0))) + (clobber (match_scratch:DI 4 "=r,r"))] + "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])" + "@ + rldicr. %4,%1,%H2,%S3 + #" + [(set_attr "type" "delayed_compare") + (set_attr "length" "4,8")]) + +(define_split + [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "") + (compare:CC + (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "const_int_operand" "")) + (match_operand:DI 3 "mask64_operand" "")) + (const_int 0))) + (clobber (match_scratch:DI 4 ""))] + "TARGET_POWERPC64 && reload_completed + && includes_rldicr_lshift_p (operands[2], operands[3])" + [(set (match_dup 4) + (and:DI (ashift:DI (match_dup 1) (match_dup 2)) + (match_dup 3))) + (set (match_dup 0) + (compare:CC (match_dup 4) + (const_int 0)))] + "") + +(define_insn "*ashldi3_internal9" + [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y") + (compare:CC + (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "const_int_operand" "i,i")) + (match_operand:DI 3 "mask64_operand" "S,S")) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] + "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])" + "@ + rldicr. %0,%1,%H2,%S3 + #" + [(set_attr "type" "delayed_compare") + (set_attr "length" "4,8")]) + +(define_split + [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "") + (compare:CC + (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "const_int_operand" "")) + (match_operand:DI 3 "mask64_operand" "")) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "") + (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] + "TARGET_POWERPC64 && reload_completed + && includes_rldicr_lshift_p (operands[2], operands[3])" [(set (match_dup 0) (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3))) @@ -9185,8 +9115,9 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); ;; Code to initialize the TOC register... (define_insn "load_toc_aix_si" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(const_int 0)] 7))] + [(parallel [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(const_int 0)] 7)) + (use (reg:SI 2))])] "! TARGET_ELF && TARGET_32BIT" "* { @@ -9199,8 +9130,9 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); [(set_attr "type" "load")]) (define_insn "load_toc_aix_di" - [(set (match_operand:DI 0 "register_operand" "=r") - (unspec:DI [(const_int 0)] 7))] + [(parallel [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(const_int 0)] 7)) + (use (reg:DI 2))])] "! TARGET_ELF && TARGET_64BIT" "* { @@ -10330,7 +10262,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); (define_insn "" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r") (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r") - (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I"))) + (match_operand:DI 2 "scc_eq_operand" "r,O,K,J,I"))) (clobber (match_scratch:DI 3 "=r,&r,r,r,r"))] "TARGET_POWERPC64" "@ @@ -10387,7 +10319,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y") (compare:CC (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r") - (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I,r,O,K,J,I")) + (match_operand:DI 2 "scc_eq_operand" "r,O,K,J,I,r,O,K,J,I")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r") (eq:DI (match_dup 1) (match_dup 2))) @@ -10411,7 +10343,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "") (compare:CC (eq:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:DI 2 "reg_or_cint_operand" "")) + (match_operand:DI 2 "scc_eq_operand" "")) (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") (eq:DI (match_dup 1) (match_dup 2))) @@ -12575,7 +12507,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); (const_int 0)]) (const_int 0)))] "" - "crnot %E0,%j1" + "{crnor %E0,%j1,%j1|crnot %E0,%j1}" [(set_attr "type" "cr_logical")]) ;; If we are comparing the result of two comparisons, this can be done @@ -12602,27 +12534,34 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); positive_2 = branch_positive_comparison_operator (operands[3], CCEQmode); if (! positive_1) - operands[1] = gen_rtx (SImode, - rs6000_reverse_condition (GET_MODE (operands[2]), + operands[1] = gen_rtx (rs6000_reverse_condition (GET_MODE (operands[2]), GET_CODE (operands[1])), - operands[2]); + SImode, + operands[2], const0_rtx); else if (GET_MODE (operands[1]) != SImode) - operands[1] = gen_rtx (SImode, - GET_CODE (operands[1]), - operands[2]); + operands[1] = gen_rtx (GET_CODE (operands[1]), + SImode, + operands[2], const0_rtx); if (! positive_2) - operands[3] = gen_rtx (SImode, - rs6000_reverse_condition (GET_MODE (operands[4]), + operands[3] = gen_rtx (rs6000_reverse_condition (GET_MODE (operands[4]), GET_CODE (operands[3])), - operands[4]); + SImode, + operands[4], const0_rtx); else if (GET_MODE (operands[3]) != SImode) - operands[3] = gen_rtx (SImode, - GET_CODE (operands[3]), - operands[4]); + operands[3] = gen_rtx (GET_CODE (operands[3]), + SImode, + operands[4], const0_rtx); if (positive_1 == positive_2) - operands[1] = gen_rtx_NOT (SImode, operands[1]); + { + operands[1] = gen_rtx_NOT (SImode, operands[1]); + operands[5] = constm1_rtx; + } + else + { + operands[5] = const1_rtx; + } }") ;; Unconditional branch and return. @@ -12807,7 +12746,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"{bdn|bdnz} %l0\"; else return \"bdz %$+8\;b %l0\"; @@ -12831,7 +12770,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"bdz %l0\"; else return \"{bdn|bdnz} %$+8\;b %l0\"; @@ -12855,7 +12794,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"{bdn|bdnz} %l0\"; else return \"bdz %$+8\;b %l0\"; @@ -12879,7 +12818,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"bdz %l0\"; else return \"{bdn|bdnz} %$+8\;b %l0\"; @@ -12905,7 +12844,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"{bdn|bdnz} %l0\"; else return \"bdz %$+8\;b %l0\"; @@ -12929,7 +12868,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"bdz %l0\"; else return \"{bdn|bdnz} %$+8\;b %l0\"; @@ -12953,7 +12892,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"{bdn|bdnz} %l0\"; else return \"bdz %$+8\;b %l0\"; @@ -12977,7 +12916,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"bdz %l0\"; else return \"{bdn|bdnz} %$+8\;b %l0\"; @@ -13003,7 +12942,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"bdz %l0\"; else return \"{bdn|bdnz} %$+8\;b %l0\"; @@ -13027,7 +12966,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"{bdn|bdnz} %l0\"; else return \"bdz %$+8\;b %l0\"; @@ -13051,7 +12990,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"bdz %l0\"; else return \"{bdn|bdnz} %$+8\;b %l0\"; @@ -13075,7 +13014,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); { if (which_alternative != 0) return \"#\"; - else if (get_attr_length (insn) == 8) + else if (get_attr_length (insn) == 4) return \"{bdn|bdnz} %l0\"; else return \"bdz %$+8\;b %l0\"; @@ -13374,118 +13313,67 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); "TARGET_64BIT" "b %z2") -; This is used in compiling the routines __throw and __rethrow. -; It's a little different to the usual definition... - -(define_expand "eh_epilogue" - [(use (match_operand 0 "general_operand" "r")) - (use (match_operand 1 "general_operand" "r")) - (use (match_operand 2 "general_operand" "c"))] +; This is used in compiling the unwind routines. +(define_expand "eh_return" + [(use (match_operand 0 "general_operand" "")) + (use (match_operand 1 "general_operand" ""))] "" " { - rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); - rtx insn; - - /* This is required for binary compatibility. If it's wrong, - it probably means that eh_regs() in except.c is broken. */ - if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != 3) - abort(); - - /* These can be anything that doesn't interfere with the epilogue. */ - if (GET_CODE (operands[1]) != REG || REGNO (operands[1]) != 4) - { - rtx r = gen_rtx_REG (Pmode, 4); - emit_move_insn (r, operands[1]); - operands[1] = r; - } - - if (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) != COUNT_REGISTER_REGNUM) - { - rtx r = gen_rtx_REG (Pmode, COUNT_REGISTER_REGNUM); - emit_move_insn (r, operands[2]); - operands[2] = r; - } - #if TARGET_AIX - rs6000_emit_eh_toc_restore (operands[1]); + rs6000_emit_eh_toc_restore (operands[0]); #endif - - emit_insn (gen_eh_reg_restore ()); - - if (Pmode == SImode) - emit_insn (gen_addsi3 (stack_reg, stack_reg, operands[1])); - else - emit_insn (gen_adddi3 (stack_reg, stack_reg, operands[1])); - - if (Pmode == SImode) - insn = emit_jump_insn (gen_return_eh_si (operands[2])); + if (TARGET_32BIT) + emit_insn (gen_eh_set_lr_si (operands[1])); else - insn = emit_jump_insn (gen_return_eh_di (operands[2])); - emit_barrier_after (insn); - + emit_insn (gen_eh_set_lr_di (operands[1])); + emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]); DONE; }") -; We can't expand this before we know which registers are restored, -; but we do want to expand it before flow2 because that way flow2 can -; remove the redundant loads of the link register. -(define_expand "eh_reg_restore" - [(unspec_volatile [(const_int 0)] 9)] - "" - "") +; We can't expand this before we know where the link register is stored. +(define_insn "eh_set_lr_si" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 9) + (clobber (match_scratch:SI 1 "=&r"))] + "TARGET_32BIT" + "#") + +(define_insn "eh_set_lr_di" + [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 9) + (clobber (match_scratch:DI 1 "=&r"))] + "TARGET_64BIT" + "#") (define_split - [(unspec_volatile [(const_int 0)] 9)] - "reload_completed && TARGET_SCHED_PROLOG" - [(unspec_volatile [(const_int 0)] 9)] + [(unspec_volatile [(match_operand 0 "register_operand" "")] 9) + (clobber (match_scratch 1 ""))] + "reload_completed" + [(const_int 0)] " { - rs6000_emit_epilogue (TRUE); - DONE; -}") - -(define_insn "" - [(unspec_volatile [(const_int 0)] 9)] - "" - "* -{ - if (TARGET_SCHED_PROLOG) - return \"#\"; - - /* This is slightly ugly, but at least we don't have multiple - copies of the epilogue-emitting code. */ - start_sequence (); - - /* A NOTE_INSN_DELETED is supposed to be at the start - and end of the \"toplevel\" insn chain. */ - emit_note (0, NOTE_INSN_DELETED); - rs6000_emit_epilogue (TRUE); - emit_note (0, NOTE_INSN_DELETED); - - if (TARGET_DEBUG_STACK) - debug_rtx_list (get_insns(), 100); - final (get_insns(), asm_out_file, FALSE, FALSE); - end_sequence (); - return \"\"; -}") + rs6000_stack_t *info = rs6000_stack_info (); + if (info->lr_save_p) + { + rtx frame_rtx = stack_pointer_rtx; + int sp_offset = 0; + rtx tmp; -(define_insn "return_eh_si" - [(return) - (use (match_operand:SI 0 "register_operand" "lc")) - (use (reg:SI 2)) - (use (reg:SI 3))] - "TARGET_32BIT" - "b%T0" - [(set_attr "type" "jmpreg")]) + if (frame_pointer_needed + || current_function_calls_alloca + || info->total_size > 32767) + { + emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx)); + frame_rtx = operands[1]; + } + else if (info->push_p) + sp_offset = info->total_size; -(define_insn "return_eh_di" - [(return) - (use (match_operand:DI 0 "register_operand" "lc")) - (use (reg:DI 2)) - (use (reg:DI 3))] - "TARGET_64BIT" - "b%T0" - [(set_attr "type" "jmpreg")]) + tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset); + tmp = gen_rtx_MEM (Pmode, tmp); + emit_move_insn (tmp, operands[0]); + } + else + emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]); + DONE; +}") |