--- gcc/config/i386.md 2018/04/24 16:55:13 1.1.1.2 +++ gcc/config/i386.md 2018/04/24 16:58:50 1.1.1.4 @@ -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 @@ -1596,7 +1622,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 +1704,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))