--- gcc/config/i386.md 2018/04/24 17:51:37 1.1 +++ gcc/config/i386.md 2018/04/24 17:55:11 1.1.1.2 @@ -252,30 +252,60 @@ ;; logical compare -;; ??? What if we are testing one byte of an offsettable memory reference? (define_insn "" [(set (cc0) - (and:SI (match_operand:SI 0 "general_operand" "%rm") + (and:SI (match_operand:SI 0 "general_operand" "%ro") (match_operand:SI 1 "general_operand" "ri")))] "" "* { /* For small integers, we may actually use testb. */ if (GET_CODE (operands[1]) == CONST_INT - && (INTVAL (operands[1]) & ~0xffff) == 0 - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + && ! NON_QI_REG_P (operands[0])) { /* We may set the sign bit spuriously. */ - cc_status.flags |= CC_NOT_NEGATIVE; - if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[1]) & ~0xff) == 0) - return AS2 (test%B0,%1,%b0); + if ((INTVAL (operands[1]) & ~0xff) == 0) + { + cc_status.flags |= CC_NOT_NEGATIVE; + return AS2 (test%B0,%1,%b0); + } - if (QI_REG_P (operands[0]) && (INTVAL (operands[1]) & ~0xff00) == 0) + if ((INTVAL (operands[1]) & ~0xff00) == 0) { + cc_status.flags |= CC_NOT_NEGATIVE; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) >> 8); - return AS2 (test%B0,%1,%h0); + + if (QI_REG_P (operands[0])) + return AS2 (test%B0,%1,%h0); + else + { + operands[0] = adj_offsettable_operand (operands[0], 1); + return AS2 (test%B0,%1,%b0); + } + } + + if (GET_CODE (operands[0]) == MEM + && (INTVAL (operands[1]) & ~0xff0000) == 0) + { + cc_status.flags |= CC_NOT_NEGATIVE; + operands[1] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[1]) >> 16); + + operands[0] = adj_offsettable_operand (operands[0], 2); + return AS2 (test%B0,%1,%b0); + } + + if (GET_CODE (operands[0]) == MEM + && (INTVAL (operands[1]) & ~0xff000000) == 0) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + (INTVAL (operands[1]) >> 24) & 0xff); + + operands[0] = adj_offsettable_operand (operands[0], 3); + return AS2 (test%B0,%1,%b0); } } @@ -287,18 +317,18 @@ (define_insn "" [(set (cc0) - (and:HI (match_operand:HI 0 "general_operand" "%rm") + (and:HI (match_operand:HI 0 "general_operand" "%ro") (match_operand:HI 1 "general_operand" "ri")))] "" "* { if (GET_CODE (operands[1]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + && ! NON_QI_REG_P (operands[0])) { - /* Can we ignore the upper byte? */ - if (! NON_QI_REG_P (operands[0]) - && (INTVAL (operands[1]) & 0xff00) == 0) + if ((INTVAL (operands[1]) & 0xff00) == 0) { + /* ??? This might not be necessary. */ if (INTVAL (operands[1]) & 0xffff0000) operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xff); @@ -308,13 +338,18 @@ return AS2 (test%B0,%1,%b0); } - /* Can we ignore the lower byte? */ - /* ??? what about offsettable memory references? */ - if (QI_REG_P (operands[0]) && (INTVAL (operands[1]) & 0xff) == 0) + if ((INTVAL (operands[1]) & 0xff) == 0) { operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) >> 8) & 0xff); - return AS2 (test%B0,%1,%h0); + + if (QI_REG_P (operands[0])) + return AS2 (test%B0,%1,%h0); + else + { + operands[0] = adj_offsettable_operand (operands[0], 1); + return AS2 (test%B0,%1,%b0); + } } } @@ -747,47 +782,6 @@ ;;- conversion instructions ;;- NONE -;;- truncation instructions - -(define_insn "truncsiqi2" - [(set (match_operand:QI 0 "general_operand" "=q,qm") - (truncate:QI - (match_operand:SI 1 "general_operand" "qim,qn")))] - "" - "* -{ - if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT) - return AS2 (mov%L0,%1,%k0); - - return AS2 (mov%B0,%b1,%0); -}") - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "general_operand" "=q,qm") - (truncate:QI - (match_operand:HI 1 "general_operand" "qim,qn")))] - "" - "* -{ - if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT) - return AS2 (mov%L0,%1,%k0); - - return AS2 (mov%B0,%b1,%0); -}") - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "general_operand" "=r,rm") - (truncate:HI - (match_operand:SI 1 "general_operand" "rim,rn")))] - "" - "* -{ - if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT) - return AS2 (mov%L0,%1,%k0); - - return AS2 (mov%W0,%w1,%0); -}") - ;;- zero extension instructions ;; See comments by `andsi' for when andl is faster than movzx. @@ -1060,7 +1054,7 @@ operands[1] = copy_to_mode_reg (SFmode, operands[1]); }") -;; These match a signed convertion of either DFmode or SFmode to DImode. +;; These match a signed conversion of either DFmode or SFmode to DImode. (define_insn "" [(set (match_operand:DI 0 "general_operand" "=m,!*r") @@ -1113,7 +1107,7 @@ ;; Conversion between fixed point and floating point. ;; The actual pattern that matches these is at the end of this file. -;; ??? Possibly repsent floatunssidf2 here in gcc2. +;; ??? Possibly represent floatunssidf2 here in gcc2. (define_expand "floatsisf2" [(set (match_operand:SF 0 "register_operand" "") @@ -1860,7 +1854,7 @@ CC_STATUS_INIT; if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%0); + return AS1 (not%B0,%b0); return AS2 (xor%B0,%2,%b0); } @@ -1901,7 +1895,7 @@ INTVAL (operands[2]) & 0xffff); if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%0); + return AS1 (not%B0,%b0); return AS2 (xor%B0,%2,%b0); } @@ -2622,6 +2616,10 @@ ;; i486, it is faster to copy a MEM to REG and then use bt, than to use ;; bt on the MEM directly. +;; ??? The first argument of a zero_extract must not be reloaded, so +;; don't allow a MEM in the operand predicate without allowing it in the +;; constraint. + (define_insn "" [(set (cc0) (zero_extract (match_operand:QI 0 "register_operand" "q") (const_int 1) @@ -2643,36 +2641,12 @@ RET; }") -(define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") - (const_int 1) - (match_operand:SI 1 "general_operand" "ri"))) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "* -{ - /* Copy memory to scratch register; pretend it was there to start with. */ - if (GET_CODE (operands[0]) == MEM) - { - output_asm_insn (AS2 (mov%L2,%0,%2), operands); - operands[0] = operands[2]; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (operands[1])); - output_asm_insn (AS2 (test%L0,%1,%0), operands); - } - else - { - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0])); - cc_status.flags |= CC_Z_IN_NOT_C; - output_asm_insn (AS2 (bt%L0,%1,%0), operands); - } - RET; -}") +;; ??? The first argument of a zero_extract must not be reloaded, so +;; don't allow a MEM in the operand predicate without allowing it in the +;; constraint. (define_insn "" - [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "r") + [(set (cc0) (zero_extract (match_operand:HI 0 "register_operand" "r") (const_int 1) (match_operand:SI 1 "general_operand" "ri")))] "" @@ -2680,8 +2654,32 @@ { if (GET_CODE (operands[1]) == CONST_INT) { - operands[1] = gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (operands[1])); - output_asm_insn (AS2 (test%W0,%1,%0), operands); + if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 8) + { + cc_status.flags |= CC_NOT_NEGATIVE; + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 1 << INTVAL (operands[1])); + + output_asm_insn (AS2 (test%B0,%1,%b0), operands); + } + else if (QI_REG_P (operands[0])) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 1 << (INTVAL (operands[1]) - 8)); + + output_asm_insn (AS2 (test%B0,%1,%h0), operands); + } + else + { + /* ??? This will never set CC to negative, even if we test + the sign bit of the HImode reg. But CC0 is only tested + for EQ and NE after this insn. */ + + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 1 << INTVAL (operands[1])); + + output_asm_insn (AS2 (test%L0,%1,%k0), operands); + } } else { @@ -2691,8 +2689,12 @@ RET; }") +;; ??? The first argument of a zero_extract must not be reloaded, so +;; don't allow a MEM in the operand predicate without allowing it in the +;; constraint. + (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "r") + [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") (const_int 1) (match_operand:SI 1 "general_operand" "ri")))] "" @@ -2700,8 +2702,29 @@ { if (GET_CODE (operands[1]) == CONST_INT) { - operands[1] = gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (operands[1])); - output_asm_insn (AS2 (test%L0,%1,%0), operands); + if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 8) + { + cc_status.flags |= CC_NOT_NEGATIVE; + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 1 << INTVAL (operands[1])); + + output_asm_insn (AS2 (test%B0,%1,%b0), operands); + } + else if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 16) + { + cc_status.flags |= CC_NOT_NEGATIVE; + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 1 << (INTVAL (operands[1]) - 8)); + + output_asm_insn (AS2 (test%B0,%1,%h0), operands); + } + else + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + 1 << INTVAL (operands[1])); + + output_asm_insn (AS2 (test%L0,%1,%0), operands); + } } else { @@ -3079,31 +3102,29 @@ ;; Emit code here to do the range checking and make the index zero based. (define_expand "casesi" - [(parallel + [(set (match_dup 5) + (minus:SI (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))) + (set (cc0) + (compare (match_dup 5) + (match_operand:SI 2 "general_operand" ""))) + (set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 4 "" "")) + (pc))) + (parallel [(set (pc) - (if_then_else (leu (minus:SI - (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "const_int_operand" "")) - (match_operand:SI 2 "const_int_operand" "")) - (plus:SI (mem:SI (plus:SI (pc) - (minus:SI (match_dup 0) - (match_dup 1)))) - (label_ref (match_operand 3 "" ""))) - (pc))) - (use (label_ref (match_operand 4 "" ""))) - (clobber (match_scratch:SI 5 ""))])] + (minus:SI (reg:SI 3) + (mem:SI (plus:SI (mult:SI (match_dup 5) + (const_int 4)) + (label_ref (match_operand 3 "" "")))))) + (clobber (match_scratch:SI 6 ""))])] "flag_pic" " { - rtx reg = gen_reg_rtx (SImode); - + operands[5] = gen_reg_rtx (SImode); current_function_uses_pic_offset_table = 1; - - emit_insn (gen_subsi3 (reg, operands[0], operands[1])); - emit_insn (gen_cmpsi (reg, operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); - operands[0] = reg; - operands[1] = CONST0_RTX (SImode); }") ;; Implement a casesi insn. @@ -3137,30 +3158,25 @@ (define_insn "" [(set (pc) - (if_then_else (leu (minus:SI - (match_operand:SI 0 "general_operand" "r") - (match_operand:SI 1 "const_int_operand" "i")) - (match_operand:SI 2 "const_int_operand" "i")) - (plus:SI (mem:SI (plus:SI (pc) - (minus:SI (match_dup 0) - (match_dup 1)))) - (label_ref (match_operand 3 "" ""))) - (pc))) - (use (label_ref (match_operand 4 "" ""))) - (clobber (match_scratch:SI 5 "=&r"))] + (minus:SI (reg:SI 3) + (mem:SI (plus:SI + (mult:SI (match_operand:SI 0 "register_operand" "r") + (const_int 4)) + (label_ref (match_operand 1 "" "")))))) + (clobber (match_scratch:SI 2 "=&r"))] "" "* { rtx xops[4]; - xops[0] = pic_offset_table_rtx; - xops[1] = operands[5]; - xops[2] = operands[3]; - xops[3] = operands[0]; - - output_asm_insn (AS2 (mov%L1,%0,%1), xops); - output_asm_insn (\"sub%L1 %l2@GOTOFF(%0,%3,4),%1\", xops); - output_asm_insn (AS1 (jmp,%*%1), xops); + xops[0] = operands[0]; + xops[1] = operands[1]; + xops[2] = operands[2]; + xops[3] = pic_offset_table_rtx; + + output_asm_insn (AS2 (mov%L2,%3,%2), xops); + output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops); + output_asm_insn (AS1 (jmp,%*%2), xops); ASM_OUTPUT_ALIGN_CODE (asm_out_file); RET; }") @@ -3418,7 +3434,7 @@ #ifdef INTEL_SYNTAX output_asm_insn (\"rep movsd\", xops); #else - output_asm_insn (\"rep\;movs%L1\", xops); + output_asm_insn (\"rep\;movsl\", xops); #endif } if (INTVAL (operands[2]) & 0x02) @@ -3451,8 +3467,8 @@ (define_insn "" [(set (match_operand:QI 0 "general_operand" "=q") - (compare (mem:BLK (match_operand:SI 1 "general_operand" "D")) - (mem:BLK (match_operand:SI 2 "general_operand" "S")))) + (compare (mem:BLK (match_operand:SI 1 "general_operand" "S")) + (mem:BLK (match_operand:SI 2 "general_operand" "D")))) (use (match_operand:SI 3 "general_operand" "c")) (use (match_operand:SI 4 "immediate_operand" "i")) (clobber (match_dup 1)) @@ -3478,8 +3494,8 @@ (define_insn "" [(set (cc0) - (compare (mem:BLK (match_operand:SI 0 "general_operand" "D")) - (mem:BLK (match_operand:SI 1 "general_operand" "S")))) + (compare (mem:BLK (match_operand:SI 0 "general_operand" "S")) + (mem:BLK (match_operand:SI 1 "general_operand" "D")))) (use (match_operand:SI 2 "general_operand" "c")) (use (match_operand:SI 3 "immediate_operand" "i")) (clobber (match_dup 0))