Ticket #3242: gcc-sparc-ticket-3242-v2.patch
File gcc-sparc-ticket-3242-v2.patch, 13.5 KB (added by Sebastian Huber, on 12/19/17 at 08:36:20) |
---|
-
gcc/config/sparc/sparc.c
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 83ca1dcc617..b9c8dcc57c1 100644
a b mem_ref (rtx x) 914 914 return NULL_RTX; 915 915 } 916 916 917 /* True if any of INSN's source register(s) is REG. */ 918 919 static bool 920 insn_uses_reg_p (rtx_insn *insn, unsigned int reg) 921 { 922 extract_insn (insn); 923 return ((REG_P (recog_data.operand[1]) 924 && REGNO (recog_data.operand[1]) == reg) 925 || (recog_data.n_operands == 3 926 && REG_P (recog_data.operand[2]) 927 && REGNO (recog_data.operand[2]) == reg)); 928 } 929 930 /* True if INSN is a floating-point division or square-root. */ 931 932 static bool 933 div_sqrt_insn_p (rtx_insn *insn) 934 { 935 if (GET_CODE (PATTERN (insn)) != SET) 936 return false; 937 938 switch (get_attr_type (insn)) 939 { 940 case TYPE_FPDIVS: 941 case TYPE_FPSQRTS: 942 case TYPE_FPDIVD: 943 case TYPE_FPSQRTD: 944 return true; 945 default: 946 return false; 947 } 948 } 949 950 /* True if INSN is a floating-point instruction. */ 951 952 static bool 953 fpop_insn_p (rtx_insn *insn) 954 { 955 if (GET_CODE (PATTERN (insn)) != SET) 956 return false; 957 958 switch (get_attr_type (insn)) 959 { 960 case TYPE_FPMOVE: 961 case TYPE_FPCMOVE: 962 case TYPE_FP: 963 case TYPE_FPCMP: 964 case TYPE_FPMUL: 965 case TYPE_FPDIVS: 966 case TYPE_FPSQRTS: 967 case TYPE_FPDIVD: 968 case TYPE_FPSQRTD: 969 return true; 970 default: 971 return false; 972 } 973 } 974 975 /* True if INSN is an atomic instruction. */ 976 977 static bool 978 atomic_insn_for_leon3_p (rtx_insn *insn) 979 { 980 switch (INSN_CODE (insn)) 981 { 982 case CODE_FOR_swapsi: 983 case CODE_FOR_ldstub: 984 case CODE_FOR_atomic_compare_and_swap_leon3_1: 985 return true; 986 default: 987 return false; 988 } 989 } 990 917 991 /* We use a machine specific pass to enable workarounds for errata. 918 992 919 993 We need to have the (essentially) final form of the insn stream in order … … sparc_do_work_around_errata (void) 939 1013 { 940 1014 bool insert_nop = false; 941 1015 rtx set; 1016 rtx_insn *jump; 1017 rtx_sequence *seq; 942 1018 943 1019 /* Look into the instruction in a delay slot. */ 944 if (NONJUMP_INSN_P (insn)) 945 if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn))) 1020 if (NONJUMP_INSN_P (insn) 1021 && (seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))) 1022 { 1023 jump = seq->insn (0); 946 1024 insn = seq->insn (1); 1025 } 1026 else if (JUMP_P (insn)) 1027 jump = insn; 1028 else 1029 jump = NULL; 1030 1031 /* Place a NOP at the branch target of an integer branch if it is a 1032 floating-point operation or a floating-point branch. */ 1033 if (sparc_fix_gr712rc 1034 && jump 1035 && jump_to_label_p (jump) 1036 && get_attr_branch_type (jump) == BRANCH_TYPE_ICC) 1037 { 1038 rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump)); 1039 if (target 1040 && (fpop_insn_p (target) 1041 || (JUMP_P (target) 1042 && get_attr_branch_type (target) == BRANCH_TYPE_FCC))) 1043 emit_insn_before (gen_nop (), target); 1044 } 1045 1046 /* Insert a NOP between load instruction and atomic instruction. Insert 1047 a NOP at branch target if there is a load in delay slot and an atomic 1048 instruction at branch target. */ 1049 if (sparc_fix_ut700 1050 && NONJUMP_INSN_P (insn) 1051 && (set = single_set (insn)) != NULL_RTX 1052 && mem_ref (SET_SRC (set)) 1053 && REG_P (SET_DEST (set))) 1054 { 1055 if (jump && jump_to_label_p (jump)) 1056 { 1057 rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump)); 1058 if (target && atomic_insn_for_leon3_p (target)) 1059 emit_insn_before (gen_nop (), target); 1060 } 1061 1062 next = next_active_insn (insn); 1063 if (!next) 1064 break; 1065 1066 if (atomic_insn_for_leon3_p (next)) 1067 insert_nop = true; 1068 } 1069 1070 /* Look for a sequence that starts with a fdiv or fsqrt instruction and 1071 ends with another fdiv or fsqrt instruction with no dependencies on 1072 the former, along with an appropriate pattern in between. */ 1073 if (sparc_fix_lost_divsqrt 1074 && NONJUMP_INSN_P (insn) 1075 && div_sqrt_insn_p (insn)) 1076 { 1077 int i; 1078 int fp_found = 0; 1079 rtx_insn *after; 1080 1081 const unsigned int dest_reg = REGNO (SET_DEST (single_set (insn))); 1082 1083 next = next_active_insn (insn); 1084 if (!next) 1085 break; 1086 1087 for (after = next, i = 0; i < 4; i++) 1088 { 1089 /* Count floating-point operations. */ 1090 if (i != 3 && fpop_insn_p (after)) 1091 { 1092 /* If the insn uses the destination register of 1093 the div/sqrt, then it cannot be problematic. */ 1094 if (insn_uses_reg_p (after, dest_reg)) 1095 break; 1096 fp_found++; 1097 } 1098 1099 /* Count floating-point loads. */ 1100 if (i != 3 1101 && (set = single_set (after)) != NULL_RTX 1102 && REG_P (SET_DEST (set)) 1103 && REGNO (SET_DEST (set)) > 31) 1104 { 1105 /* If the insn uses the destination register of 1106 the div/sqrt, then it cannot be problematic. */ 1107 if (REGNO (SET_DEST (set)) == dest_reg) 1108 break; 1109 fp_found++; 1110 } 1111 1112 /* Check if this is a problematic sequence. */ 1113 if (i > 1 1114 && fp_found >= 2 1115 && div_sqrt_insn_p (after)) 1116 { 1117 /* If this is the short version of the problematic 1118 sequence we add two NOPs in a row to also prevent 1119 the long version. */ 1120 if (i == 2) 1121 emit_insn_before (gen_nop (), next); 1122 insert_nop = true; 1123 break; 1124 } 1125 1126 /* No need to scan past a second div/sqrt. */ 1127 if (div_sqrt_insn_p (after)) 1128 break; 1129 1130 /* Insert NOP before branch. */ 1131 if (i < 3 1132 && (!NONJUMP_INSN_P (after) 1133 || GET_CODE (PATTERN (after)) == SEQUENCE)) 1134 { 1135 insert_nop = true; 1136 break; 1137 } 1138 1139 after = next_active_insn (after); 1140 if (!after) 1141 break; 1142 } 1143 } 947 1144 948 1145 /* Look for either of these two sequences: 949 1146 … … sparc_do_work_around_errata (void) 1003 1200 then the sequence cannot be problematic. */ 1004 1201 if (i == 0) 1005 1202 { 1006 if (( (set = single_set (after)) != NULL_RTX)1007 && (MEM_P (SET_DEST (set)) || MEM_P(SET_SRC (set))))1203 if ((set = single_set (after)) != NULL_RTX 1204 && (MEM_P (SET_DEST (set)) || mem_ref (SET_SRC (set)))) 1008 1205 break; 1009 1206 1010 1207 after = next_active_insn (after); … … sparc_do_work_around_errata (void) 1014 1211 1015 1212 /* Add NOP if third instruction is a store. */ 1016 1213 if (i == 1 1017 && ( (set = single_set (after)) != NULL_RTX)1214 && (set = single_set (after)) != NULL_RTX 1018 1215 && MEM_P (SET_DEST (set))) 1019 1216 insert_nop = true; 1020 1217 } 1021 1218 } 1022 else 1219 1023 1220 /* Look for a single-word load into an odd-numbered FP register. */ 1024 if (sparc_fix_at697f1025 && NONJUMP_INSN_P (insn)1026 && (set = single_set (insn)) != NULL_RTX1027 && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 41028 && MEM_P(SET_SRC (set))1029 && REG_P (SET_DEST (set))1030 && REGNO (SET_DEST (set)) > 311031 && REGNO (SET_DEST (set)) % 2 != 0)1221 else if (sparc_fix_at697f 1222 && NONJUMP_INSN_P (insn) 1223 && (set = single_set (insn)) != NULL_RTX 1224 && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4 1225 && mem_ref (SET_SRC (set)) 1226 && REG_P (SET_DEST (set)) 1227 && REGNO (SET_DEST (set)) > 31 1228 && REGNO (SET_DEST (set)) % 2 != 0) 1032 1229 { 1033 1230 /* The wrong dependency is on the enclosing double register. */ 1034 1231 const unsigned int x = REGNO (SET_DEST (set)) - 1; … … sparc_do_work_around_errata (void) 1095 1292 && NONJUMP_INSN_P (insn) 1096 1293 && (set = single_set (insn)) != NULL_RTX 1097 1294 && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) <= 4 1098 && mem_ref (SET_SRC (set)) != NULL_RTX 1295 && (mem_ref (SET_SRC (set)) != NULL_RTX 1296 || INSN_CODE (insn) == CODE_FOR_movsi_pic_gotdata_op) 1099 1297 && REG_P (SET_DEST (set)) 1100 1298 && REGNO (SET_DEST (set)) < 32) 1101 1299 { … … sparc_do_work_around_errata (void) 1133 1331 && REGNO (src) != REGNO (x))) 1134 1332 && !reg_mentioned_p (x, XEXP (dest, 0))) 1135 1333 insert_nop = true; 1334 1335 /* GOT accesses uses LD. */ 1336 else if (INSN_CODE (next) == CODE_FOR_movsi_pic_gotdata_op 1337 && !reg_mentioned_p (x, XEXP (XEXP (src, 0), 1))) 1338 insert_nop = true; 1136 1339 } 1137 1340 } 1138 1341 … … public: 1272 1475 /* opt_pass methods: */ 1273 1476 virtual bool gate (function *) 1274 1477 { 1275 return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst; 1478 return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst 1479 || sparc_fix_gr712rc || sparc_fix_ut700 || sparc_fix_lost_divsqrt; 1276 1480 } 1277 1481 1278 1482 virtual unsigned int execute (function *) … … sparc_option_override (void) 1642 1846 if (!(target_flags_explicit & MASK_LRA)) 1643 1847 target_flags |= MASK_LRA; 1644 1848 1645 /* Enable the back-to-back store errata workaroundfor LEON3FT. */1849 /* Enable applicable errata workarounds for LEON3FT. */ 1646 1850 if (sparc_fix_ut699 || sparc_fix_ut700 || sparc_fix_gr712rc) 1851 { 1647 1852 sparc_fix_b2bst = 1; 1853 sparc_fix_lost_divsqrt = 1; 1854 } 1648 1855 1649 1856 /* Disable FsMULd for the UT699 since it doesn't work correctly. */ 1650 1857 if (sparc_fix_ut699) -
gcc/config/sparc/sparc.md
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 321c0d8b9fe..4ddbe56fbf4 100644
a b 430 430 (symbol_ref "(sparc_fix_b2bst != 0 431 431 ? FIX_B2BST_TRUE : FIX_B2BST_FALSE)")) 432 432 433 (define_attr "fix_lost_divsqrt" "false,true" 434 (symbol_ref "(sparc_fix_lost_divsqrt != 0 435 ? FIX_LOST_DIVSQRT_TRUE : FIX_LOST_DIVSQRT_FALSE)")) 436 437 (define_attr "fix_gr712rc" "false,true" 438 (symbol_ref "(sparc_fix_gr712rc != 0 439 ? FIX_GR712RC_TRUE : FIX_GR712RC_FALSE)")) 440 433 441 ;; Length (in # of insns). 434 442 ;; Beware that setting a length greater or equal to 3 for conditional branches 435 443 ;; has a side-effect (see output_cbranch and output_v9branch). … … 577 585 (define_attr "in_branch_delay" "false,true" 578 586 (cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") 579 587 (const_string "false") 588 (and (eq_attr "fix_lost_divsqrt" "true") 589 (eq_attr "type" "fpdivs,fpsqrts,fpdivd,fpsqrtd")) 590 (const_string "false") 580 591 (and (eq_attr "fix_b2bst" "true") (eq_attr "type" "store,fpstore")) 581 592 (const_string "false") 582 593 (and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload")) … … 590 601 (const_string "true") 591 602 ] (const_string "false"))) 592 603 604 (define_attr "in_integer_branch_annul_delay" "false,true" 605 (cond [(and (eq_attr "fix_gr712rc" "true") 606 (eq_attr "type" "fp,fpcmp,fpmove,fpcmove,fpmul, 607 fpdivs,fpsqrts,fpdivd,fpsqrtd")) 608 (const_string "false") 609 (eq_attr "in_branch_delay" "true") 610 (const_string "true") 611 ] (const_string "false"))) 612 593 613 (define_delay (eq_attr "type" "call") 594 614 [(eq_attr "in_call_delay" "true") (nil) (nil)]) 595 615 … … 599 619 (define_delay (eq_attr "type" "return") 600 620 [(eq_attr "in_return_delay" "true") (nil) (nil)]) 601 621 602 (define_delay (eq_attr "type" "branch") 622 (define_delay (and (eq_attr "type" "branch") 623 (not (eq_attr "branch_type" "icc"))) 603 624 [(eq_attr "in_branch_delay" "true") (nil) (eq_attr "in_branch_delay" "true")]) 604 625 626 (define_delay (and (eq_attr "type" "branch") 627 (eq_attr "branch_type" "icc")) 628 [(eq_attr "in_branch_delay" "true") (nil) 629 (eq_attr "in_integer_branch_annul_delay" "true")]) 630 605 631 (define_delay (eq_attr "type" "uncond_branch") 606 632 [(eq_attr "in_branch_delay" "true") (nil) (nil)]) 607 633 -
gcc/config/sparc/sparc.opt
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index 22267f50e90..71ead75831d 100644
a b Enable workarounds for the errata of the GR712RC processor. 253 253 TargetVariable 254 254 unsigned int sparc_fix_b2bst 255 255 256 ;; Enable workaround for GRLIB-TN-0013 errata 257 TargetVariable 258 unsigned int sparc_fix_lost_divsqrt 259 256 260 Mask(LONG_DOUBLE_128) 257 261 ;; Use 128-bit long double 258 262 -
gcc/config/sparc/sync.md
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md index 1593bdeb903..43c66e96ba3 100644
a b 212 212 "cas<modesuffix>\t%1, %2, %0" 213 213 [(set_attr "type" "multi")]) 214 214 215 (define_insn " *atomic_compare_and_swap_leon3_1"215 (define_insn "atomic_compare_and_swap_leon3_1" 216 216 [(set (match_operand:SI 0 "register_operand" "=r") 217 217 (match_operand:SI 1 "mem_noofs_operand" "+w")) 218 218 (set (match_dup 1) … … 222 222 UNSPECV_CAS))] 223 223 "TARGET_LEON3" 224 224 { 225 if (sparc_fix_gr712rc) 226 output_asm_insn (".align\t16", operands); 225 227 if (TARGET_SV_MODE) 226 228 return "casa\t%1 0xb, %2, %0"; /* ASI for supervisor data space. */ 227 229 else 228 230 return "casa\t%1 0xa, %2, %0"; /* ASI for user data space. */ 229 231 } 230 [(set_attr "type" "multi")]) 232 [(set_attr "type" "multi") 233 (set (attr "length") (if_then_else (eq_attr "fix_gr712rc" "true") 234 (const_int 4) (const_int 1)))]) 231 235 232 236 (define_insn "*atomic_compare_and_swapdi_v8plus" 233 237 [(set (match_operand:DI 0 "register_operand" "=h") … … 275 279 (set (match_dup 1) 276 280 (match_operand:SI 2 "register_operand" "0"))] 277 281 "(TARGET_V8 || TARGET_V9) && !sparc_fix_ut699" 278 "swap\t%1, %0" 279 [(set_attr "type" "multi")]) 282 { 283 if (sparc_fix_gr712rc) 284 return ".align\t16\n\tswap\t%1, %0"; 285 else 286 return "swap\t%1, %0"; 287 } 288 [(set_attr "type" "multi") 289 (set (attr "length") (if_then_else (eq_attr "fix_gr712rc" "true") 290 (const_int 4) (const_int 1)))]) 280 291 281 292 (define_expand "atomic_test_and_set" 282 293 [(match_operand:QI 0 "register_operand" "") … … 307 318 UNSPECV_LDSTUB)) 308 319 (set (match_dup 1) (const_int -1))] 309 320 "!sparc_fix_ut699" 310 "ldstub\t%1, %0" 311 [(set_attr "type" "multi")]) 321 { 322 if (sparc_fix_gr712rc) 323 return ".align\t16\n\tldstub\t%1, %0"; 324 else 325 return "ldstub\t%1, %0"; 326 } 327 [(set_attr "type" "multi") 328 (set (attr "length") (if_then_else (eq_attr "fix_gr712rc" "true") 329 (const_int 4) (const_int 1)))])