--- gcc/config/i386.md 2018/04/24 16:53:28 1.1.1.1 +++ gcc/config/i386.md 2018/04/24 17:02:31 1.1.1.6 @@ -90,7 +90,7 @@ (define_insn "tstsf" [(set (cc0) (match_operand:SF 0 "general_operand" "rm,f")) - (clobber (reg:HI 0))] + (clobber (reg:SI 0))] "TARGET_80387" "* { @@ -110,7 +110,7 @@ (define_insn "tstdf" [(set (cc0) (match_operand:DF 0 "general_operand" "rm,f")) - (clobber (reg:HI 0)) + (clobber (reg:SI 0)) ] "TARGET_80387" "* @@ -236,7 +236,7 @@ "" "* { - if (GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[0]) == MEM) + if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%L0,%1,%0); return AS2 (test%L0,%0,%1); }") @@ -248,7 +248,7 @@ "" "* { - if (GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[0]) == MEM) + if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%W0,%1,%0); return AS2 (test%W0,%0,%1); }") @@ -260,7 +260,7 @@ "" "* { - if (GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[0]) == MEM) + if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%B0,%1,%0); return AS2 (test%B0,%0,%1); }") @@ -390,15 +390,22 @@ xops[2] = stack_pointer_rtx; /* fp_pop_level--; */ output_asm_insn (AS2 (sub%L0,%1,%2), xops); - output_asm_insn (\"fstp%S0 %0\", xops); + if (top_dead_p (insn)) + output_asm_insn (\"fstp%S0 %0\", xops); + else + output_asm_insn (\"fst%S0 %0\", xops); RET; } return \"push%L0 %1\"; }") (define_insn "movsf" - [(set (match_operand:SF 0 "general_operand" "=rf,rmf,!rm") - (match_operand:SF 1 "general_operand" "m,rf,F"))] + ;; `rf' is duplicated in the second alternative + ;; to make sure an optional reload is generated + ;; for the memref in operand 0. Otherwise + ;; we could use too many hard regs. + [(set (match_operand:SF 0 "general_operand" "=rf,mrf,!rm") + (match_operand:SF 1 "general_operand" "mrf,rf,F"))] "" "* { @@ -426,7 +433,10 @@ xops[2] = stack_pointer_rtx; /* fp_pop_level--; */ output_asm_insn (AS2 (sub%L0,%1,%2), xops); - output_asm_insn (\"fstp%Q0 %0\", xops); + if (top_dead_p(insn)) + output_asm_insn (\"fstp%Q0 %0\", xops); + else + output_asm_insn (\"fst%Q0 %0\", xops); RETCOM (pushdf); } else @@ -434,8 +444,11 @@ }") (define_insn "movdf" - [(set (match_operand:DF 0 "general_operand" "=&rf,rmf,!rm") - (match_operand:DF 1 "general_operand" "m,fr,F"))] + [(set (match_operand:DF 0 "general_operand" "=rmf,&fr,!rm") + ;; `rf' is duplicated in the second alternative + ;; to make sure that optional reloads are generated + ;; for the memory reference in operand 1. + (match_operand:DF 1 "general_operand" "fr,mrf,F"))] "" "* { @@ -540,25 +553,40 @@ ;;- truncation instructions (define_insn "truncsiqi2" - [(set (match_operand:QI 0 "general_operand" "=qm,q") + [(set (match_operand:QI 0 "general_operand" "=q,m") (truncate:QI - (match_operand:SI 1 "general_operand" "qi,m")))] + (match_operand:SI 1 "general_operand" "qim,qn")))] "" - "mov%B0 %1,%0") + "* +{ + if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT) + return \"mov%L0 %1,%k0\"; + return \"mov%B0 %b1,%0\"; +}") (define_insn "trunchiqi2" - [(set (match_operand:QI 0 "general_operand" "=qm,q") + [(set (match_operand:QI 0 "general_operand" "=q,m") (truncate:QI - (match_operand:HI 1 "general_operand" "qi,m")))] + (match_operand:HI 1 "general_operand" "qim,qn")))] "" - "mov%B0 %1,%0") + "* +{ + if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT) + return \"mov%W0 %1,%w0\"; + return \"mov%B0 %b1,%0\"; +}") (define_insn "truncsihi2" - [(set (match_operand:HI 0 "general_operand" "=rm,r") + [(set (match_operand:HI 0 "general_operand" "=r,m") (truncate:HI - (match_operand:SI 1 "general_operand" "ri,m")))] + (match_operand:SI 1 "general_operand" "rim,rn")))] "" - "mov%W0 %1,%0") + "* +{ + if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT) + return \"mov%L0 %1,%k0\"; + return \"mov%W0 %w1,%0\"; +}") ;;- zero extension instructions ;; Note that the one starting from HImode comes before those for QImode @@ -598,6 +626,10 @@ "clq") */ +;; Note that the i386 programmers' manual says that the opcodes +;; are named movsx..., but the assembler on Unix does not accept that. +;; We use what the Unix assembler expects. + (define_insn "extendhisi2" [(set (match_operand:SI 0 "general_operand" "=r") (sign_extend:SI @@ -1036,9 +1068,53 @@ "*FP_CALL (\"fdiv%z0 %0\", \"fdivr%z0 %0\", 2) ") -;; Remainder instructions. +;; Divide and Remainder instructions. + +;; Copy operands 1 and 2 to new registers, so that there's no +;; danger that put_var_into_stack will mess up the sharing match_dup needs. +;; CSE will get rid of the extra pseudo regs. +;; No problem if not optimizing, since then only `register' vars +;; will get pseudo regs, and they aren't allowed to have address taken. + +(define_expand "divmodsi4" + [(parallel [(set (match_operand:SI 0 "general_operand" "=a") + (div:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "rm"))) + (set (match_operand:SI 3 "general_operand" "=&d") + (mod:SI (match_dup 1) (match_dup 2)))])] + "" + " +{ + extern int optimize; + if (optimize) + { + if (GET_CODE (operands[1]) == REG && REG_USERVAR_P (operands[1])) + operands[1] = copy_to_mode_reg (SImode, operands[1]); + if (GET_CODE (operands[2]) == REG && REG_USERVAR_P (operands[2])) + operands[2] = copy_to_mode_reg (SImode, operands[2]); + } +}") -(define_insn "divmodsi4" +(define_expand "udivmodsi4" + [(parallel [(set (match_operand:SI 0 "general_operand" "=a") + (udiv:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "rm"))) + (set (match_operand:SI 3 "general_operand" "=&d") + (umod:SI (match_dup 1) (match_dup 2)))])] + "" + " +{ + extern int optimize; + if (optimize) + { + if (GET_CODE (operands[1]) == REG && REG_USERVAR_P (operands[1])) + operands[1] = copy_to_mode_reg (SImode, operands[1]); + if (GET_CODE (operands[2]) == REG && REG_USERVAR_P (operands[2])) + operands[2] = copy_to_mode_reg (SImode, operands[2]); + } +}") + +(define_insn "" [(set (match_operand:SI 0 "general_operand" "=a") (div:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rm"))) @@ -1047,7 +1123,7 @@ "" "cltd\;idiv%L0 %2") -(define_insn "udivmodsi4" +(define_insn "" [(set (match_operand:SI 0 "general_operand" "=a") (udiv:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "general_operand" "rm"))) @@ -1472,13 +1548,15 @@ }") ;; Store-flag instructions. +;; These clear the cc_status because the output register +;; might be the same register previously tested. (define_insn "seq" [(set (match_operand:QI 0 "general_operand" "=q") (eq (cc0) (const_int 0)))] "" "* - cc_status = cc_prev_status; + CC_STATUS_INIT; return \"sete %0\"; ") @@ -1487,7 +1565,7 @@ (ne (cc0) (const_int 0)))] "" "* - cc_status = cc_prev_status; + CC_STATUS_INIT; return \"setne %0\"; ") @@ -1496,7 +1574,7 @@ (gt (cc0) (const_int 0)))] "" "* - cc_status = cc_prev_status; + CC_STATUS_INIT; OUTPUT_JUMP (\"setg %0\", \"seta %0\", 0); ") @@ -1504,43 +1582,48 @@ [(set (match_operand:QI 0 "general_operand" "=q") (gtu (cc0) (const_int 0)))] "" - "* cc_status = cc_prev_status; - return \"seta %0\"; ") + "* + CC_STATUS_INIT; + return \"seta %0\"; ") (define_insn "slt" [(set (match_operand:QI 0 "general_operand" "=q") (lt (cc0) (const_int 0)))] "" - "* cc_status = cc_prev_status; - OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); ") + "* + CC_STATUS_INIT; + OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); ") (define_insn "sltu" [(set (match_operand:QI 0 "general_operand" "=q") (ltu (cc0) (const_int 0)))] "" - "* cc_status = cc_prev_status; - return \"setb %0\"; ") + "* + CC_STATUS_INIT; + return \"setb %0\"; ") (define_insn "sge" [(set (match_operand:QI 0 "general_operand" "=q") (ge (cc0) (const_int 0)))] "" - "* cc_status = cc_prev_status; - OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); ") + "* + CC_STATUS_INIT; + OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); ") (define_insn "sgeu" [(set (match_operand:QI 0 "general_operand" "=q") (geu (cc0) (const_int 0)))] "" - "* cc_status = cc_prev_status; - return \"setae %0\"; ") + "* + CC_STATUS_INIT; + return \"setae %0\"; ") (define_insn "sle" [(set (match_operand:QI 0 "general_operand" "=q") (le (cc0) (const_int 0)))] "" "* - cc_status = cc_prev_status; + CC_STATUS_INIT; OUTPUT_JUMP (\"setle %0\", \"setbe %0\", 0); ") @@ -1548,8 +1631,9 @@ [(set (match_operand:QI 0 "general_operand" "=q") (leu (cc0) (const_int 0)))] "" - "* cc_status = cc_prev_status; - return \"setbe %0\"; ") + "* + CC_STATUS_INIT; + return \"setbe %0\"; ") ;; Basic conditional jump instructions. ;; We ignore the overflow flag for signed branch instructions. @@ -1590,7 +1674,53 @@ "" "ja %l0") -(define_insn "blt" +;; There is no jump insn to check for `<' on IEEE floats. +;; Page 17-80 in the 80387 manual says jb, but that's wrong; +;; jb checks for `not >='. So swap the operands and do `>'. +(define_expand "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + extern rtx sequence_stack; + rtx prev = XEXP (XEXP (sequence_stack, 1), 0); + rtx body = PATTERN (prev); + rtx comp; + if (GET_CODE (body) == SET) + comp = SET_SRC (body); + else + comp = SET_SRC (XVECEXP (body, 0, 0)); + + if (GET_CODE (comp) == COMPARE + ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT + : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT) + { + if (GET_CODE (comp) == COMPARE) + { + rtx op0 = XEXP (comp, 0); + rtx op1 = XEXP (comp, 1); + XEXP (comp, 0) = op1; + XEXP (comp, 1) = op0; + } + else + { + rtx new = gen_rtx (COMPARE, VOIDmode, + CONST0_RTX (GET_MODE (comp)), comp); + if (GET_CODE (body) == SET) + SET_SRC (body) = new; + else + SET_SRC (XVECEXP (body, 0, 0)) = new; + } + emit_insn (gen_bgt (operands[0])); + DONE; + } +}") + +(define_insn "" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) @@ -1626,7 +1756,51 @@ "" "jae %l0") -(define_insn "ble" +;; See comment on `blt', above. +(define_expand "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + extern rtx sequence_stack; + rtx prev = XEXP (XEXP (sequence_stack, 1), 0); + rtx body = PATTERN (prev); + rtx comp; + if (GET_CODE (body) == SET) + comp = SET_SRC (body); + else + comp = SET_SRC (XVECEXP (body, 0, 0)); + + if (GET_CODE (comp) == COMPARE + ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT + : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT) + { + if (GET_CODE (comp) == COMPARE) + { + rtx op0 = XEXP (comp, 0); + rtx op1 = XEXP (comp, 1); + XEXP (comp, 0) = op1; + XEXP (comp, 1) = op0; + } + else + { + rtx new = gen_rtx (COMPARE, VOIDmode, + CONST0_RTX (GET_MODE (comp)), comp); + if (GET_CODE (body) == SET) + SET_SRC (body) = new; + else + SET_SRC (XVECEXP (body, 0, 0)) = new; + } + emit_insn (gen_bge (operands[0])); + DONE; + } +}") + +(define_insn "" [(set (pc) (if_then_else (le (cc0) (const_int 0)) @@ -1824,18 +1998,21 @@ else output_asm_insn (\"call %1\", operands); - if (GET_MODE (operands[0]) == DFmode - || GET_MODE (operands[0]) == SFmode) - { -/* fp_pop_level++; */ - /* pop if reg dead */ - if (!FP_REG_P (operands[0])) - abort (); - if (top_dead_p (insn)) - { - POP_ONE_FP; - } - } +#ifndef FMTOWNS + if (TARGET_80387) +#endif + if (GET_MODE (operands[0]) == DFmode + || GET_MODE (operands[0]) == SFmode) + { + /* fp_pop_level++; */ + /* pop if reg dead */ + if (!FP_REG_P (operands[0])) + abort (); + if (top_dead_p (insn)) + { + POP_ONE_FP; + } + } RET; }")