--- gcc/config/i386.md 2018/04/24 16:55:13 1.1.1.2 +++ gcc/config/i386.md 2018/04/24 17:00:39 1.1.1.5 @@ -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); }") @@ -393,15 +393,19 @@ if (top_dead_p (insn)) output_asm_insn (\"fstp%S0 %0\", xops); else - output_asm_insn (\"fst%S0\", xops); + 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"))] "" "* { @@ -440,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"))] "" "* { @@ -546,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 %b1,%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 %b1,%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 %w1,%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 @@ -604,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 @@ -1042,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"))) @@ -1053,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"))) @@ -1596,7 +1666,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)) @@ -1632,7 +1748,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))