diff options
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch')
| -rw-r--r-- | recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch | 2011 |
1 files changed, 2011 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch new file mode 100644 index 0000000000..e1e89bf8af --- /dev/null +++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch | |||
| @@ -0,0 +1,2011 @@ | |||
| 1 | 2010-08-29 Chung-Lin Tang <cltang@codesourcery.com> | ||
| 2 | |||
| 3 | Backport from mainline: | ||
| 4 | |||
| 5 | 2010-04-16 Bernd Schmidt <bernds@codesourcery.com> | ||
| 6 | |||
| 7 | PR target/41514 | ||
| 8 | gcc/ | ||
| 9 | * config/arm/arm.md (cbranchsi4_insn): Renamed from "*cbranchsi4_insn". | ||
| 10 | If the previous insn is a cbranchsi4_insn with the same arguments, | ||
| 11 | omit the compare instruction. | ||
| 12 | |||
| 13 | gcc/testsuite/ | ||
| 14 | * gcc.target/arm/thumb-comparisons.c: New test. | ||
| 15 | |||
| 16 | gcc/ | ||
| 17 | * config/arm/arm.md (addsi3_cbranch): If destination is a high | ||
| 18 | register, inputs must be low registers and we need a low register | ||
| 19 | scratch. Handle alternative 2 like alternative 3. | ||
| 20 | |||
| 21 | PR target/40603 | ||
| 22 | gcc/ | ||
| 23 | * config/arm/arm.md (cbranchqi4): New pattern. | ||
| 24 | * config/arm/predicates.md (const0_operand, | ||
| 25 | cbranchqi4_comparison_operator): New predicates. | ||
| 26 | |||
| 27 | gcc/testsuite/ | ||
| 28 | * gcc.target/arm/thumb-cbranchqi.c: New test. | ||
| 29 | |||
| 30 | 2010-04-27 Bernd Schmidt <bernds@codesourcery.com> | ||
| 31 | |||
| 32 | PR target/40657 | ||
| 33 | gcc/ | ||
| 34 | * config/arm/arm.c (thumb1_extra_regs_pushed): New function. | ||
| 35 | (thumb1_expand_prologue, thumb1_output_function_prologue): Call it | ||
| 36 | here to determine which regs to push and how much stack to reserve. | ||
| 37 | |||
| 38 | gcc/testsuite/ | ||
| 39 | * gcc.target/arm/thumb-stackframe.c: New test. | ||
| 40 | |||
| 41 | 2010-07-02 Bernd Schmidt <bernds@codesourcery.com> | ||
| 42 | |||
| 43 | PR target/42835 | ||
| 44 | gcc/ | ||
| 45 | * config/arm/arm-modes.def (CC_NOTB): New mode. | ||
| 46 | * config/arm/arm.c (get_arm_condition_code): Handle it. | ||
| 47 | * config/arm/thumb2.md (thumb2_compare_scc): Delete pattern. | ||
| 48 | * config/arm/arm.md (subsi3_compare0_c): New pattern. | ||
| 49 | (compare_scc): Now a define_and_split. Add a number of extra | ||
| 50 | splitters before it. | ||
| 51 | |||
| 52 | gcc/testsuite/ | ||
| 53 | * gcc.target/arm/pr42835.c: New test. | ||
| 54 | |||
| 55 | PR target/42172 | ||
| 56 | gcc/ | ||
| 57 | * config/arm/arm.c (thumb1_rtx_costs): Improve support for SIGN_EXTEND | ||
| 58 | and ZERO_EXTEND. | ||
| 59 | (arm_rtx_costs_1): Likewise. | ||
| 60 | (arm_size_rtx_costs): Use arm_rtx_costs_1 for these codes. | ||
| 61 | * config/arm/arm.md (is_arch6): New attribute. | ||
| 62 | (zero_extendhisi2, zero_extendqisi2, extendhisi2, | ||
| 63 | extendqisi2): Tighten the code somewhat, avoiding invalid | ||
| 64 | RTL to occur in the expander patterns. | ||
| 65 | (thumb1_zero_extendhisi2): Merge with thumb1_zero_extendhisi2_v6. | ||
| 66 | (thumb1_zero_extendhisi2_v6): Delete. | ||
| 67 | (thumb1_extendhisi2): Merge with thumb1_extendhisi2_v6. | ||
| 68 | (thumb1_extendhisi2_v6): Delete. | ||
| 69 | (thumb1_extendqisi2): Merge with thumb1_extendhisi2_v6. | ||
| 70 | (thumb1_extendqisi2_v6): Delete. | ||
| 71 | (zero_extendhisi2 for register input splitter): New. | ||
| 72 | (zero_extendqisi2 for register input splitter): New. | ||
| 73 | (thumb1_extendhisi2 for register input splitter): New. | ||
| 74 | (extendhisi2 for register input splitter): New. | ||
| 75 | (extendqisi2 for register input splitter): New. | ||
| 76 | (TARGET_THUMB1 extendqisi2 for memory input splitter): New. | ||
| 77 | (arm_zero_extendhisi2): Allow nonimmediate_operand for operand 1, | ||
| 78 | and add support for a register alternative requiring a split. | ||
| 79 | (thumb1_zero_extendqisi2): Likewise. | ||
| 80 | (arm_zero_extendqisi2): Likewise. | ||
| 81 | (arm_extendhisi2): Likewise. | ||
| 82 | (arm_extendqisi2): Likewise. | ||
| 83 | |||
| 84 | gcc/testsuite/ | ||
| 85 | * gcc.target/arm/pr42172-1.c: New test. | ||
| 86 | |||
| 87 | 2010-07-05 Bernd Schmidt <bernds@codesourcery.com> | ||
| 88 | |||
| 89 | * config/arm/arm.c (get_arm_condition_code): Remove CC_NOTBmode case. | ||
| 90 | * arm-modes.def (CC_NOTB): Don't define. | ||
| 91 | * config/arm/arm.md (arm_adddi3): Generate canonical RTL. | ||
| 92 | (adddi_sesidi_di, adddi_zesidi_di): Likewise. | ||
| 93 | (LTUGEU): New code_iterator. | ||
| 94 | (cnb, optab): New corresponding code_attrs. | ||
| 95 | (addsi3_carryin_<optab>): Renamed from addsi3_carryin. Change pattern | ||
| 96 | to canonical form. Operands 1 and 2 are commutative. Parametrize | ||
| 97 | using LTUGEU. | ||
| 98 | (addsi3_carryin_shift_<optab>): Likewise. | ||
| 99 | (addsi3_carryin_alt2_<optab>): Renamed from addsi3_carryin_alt2. | ||
| 100 | Operands 1 and 2 are commutative. Parametrize using LTUGEU. | ||
| 101 | (addsi3_carryin_alt1, addsi3_carryin_alt3): Remove. | ||
| 102 | (subsi3_compare): Renamed from subsi3_compare0_c. Change CC_NOTB to | ||
| 103 | CC. | ||
| 104 | (arm_subsi3_insn): Allow constants for operand 0. | ||
| 105 | (compare_scc peephole for eq case): New. | ||
| 106 | (compare_scc splitters): Change CC_NOTB to CC. | ||
| 107 | |||
| 108 | 2010-07-09 Bernd Schmidt <bernds@codesourcery.com> | ||
| 109 | |||
| 110 | PR target/40657 | ||
| 111 | gcc/ | ||
| 112 | * config/arm/arm.c (thumb1_extra_regs_pushed): New arg FOR_PROLOGUE. | ||
| 113 | All callers changed. | ||
| 114 | Handle the case when we're called for the epilogue. | ||
| 115 | (thumb_unexpanded_epilogue): Use it. | ||
| 116 | (thumb1_expand_epilogue): Likewise. | ||
| 117 | |||
| 118 | gcc/testsuite/ | ||
| 119 | * gcc.target/arm/pr40657-1.c: New test. | ||
| 120 | * gcc.target/arm/pr40657-2.c: New test. | ||
| 121 | * gcc.c-torture/execute/pr40657.c: New test. | ||
| 122 | |||
| 123 | gcc/ | ||
| 124 | * config/arm/arm.md (addsi3_cbranch): Switch alternatives 0 and 1. | ||
| 125 | |||
| 126 | * config/arm/arm.md (Thumb-1 ldrsb peephole): New. | ||
| 127 | |||
| 128 | * config/arm/arm.md (cbranchqi4): Fix array size. | ||
| 129 | (addsi3_cbranch): Also andle alternative 2 like alternative 3 when | ||
| 130 | calculating length. | ||
| 131 | |||
| 132 | 2010-08-27 Paul Brook <paul@codesourcery.com> | ||
| 133 | |||
| 134 | gcc/ | ||
| 135 | |||
| 136 | === modified file 'gcc/config/arm/arm-modes.def' | ||
| 137 | --- old/gcc/config/arm/arm-modes.def 2010-07-29 16:58:56 +0000 | ||
| 138 | +++ new/gcc/config/arm/arm-modes.def 2010-08-31 10:00:27 +0000 | ||
| 139 | @@ -34,6 +34,8 @@ | ||
| 140 | CCFPmode should be used with floating equalities. | ||
| 141 | CC_NOOVmode should be used with SImode integer equalities. | ||
| 142 | CC_Zmode should be used if only the Z flag is set correctly | ||
| 143 | + CC_Cmode should be used if only the C flag is set correctly, after an | ||
| 144 | + addition. | ||
| 145 | CC_Nmode should be used if only the N (sign) flag is set correctly | ||
| 146 | CC_CZmode should be used if only the C and Z flags are correct | ||
| 147 | (used for DImode unsigned comparisons). | ||
| 148 | |||
| 149 | === modified file 'gcc/config/arm/arm.c' | ||
| 150 | --- old/gcc/config/arm/arm.c 2010-08-25 16:22:17 +0000 | ||
| 151 | +++ new/gcc/config/arm/arm.c 2010-08-31 10:00:27 +0000 | ||
| 152 | @@ -6443,6 +6443,7 @@ | ||
| 153 | thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer) | ||
| 154 | { | ||
| 155 | enum machine_mode mode = GET_MODE (x); | ||
| 156 | + int total; | ||
| 157 | |||
| 158 | switch (code) | ||
| 159 | { | ||
| 160 | @@ -6545,24 +6546,20 @@ | ||
| 161 | return 14; | ||
| 162 | return 2; | ||
| 163 | |||
| 164 | + case SIGN_EXTEND: | ||
| 165 | case ZERO_EXTEND: | ||
| 166 | - /* XXX still guessing. */ | ||
| 167 | - switch (GET_MODE (XEXP (x, 0))) | ||
| 168 | - { | ||
| 169 | - case QImode: | ||
| 170 | - return (1 + (mode == DImode ? 4 : 0) | ||
| 171 | - + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); | ||
| 172 | - | ||
| 173 | - case HImode: | ||
| 174 | - return (4 + (mode == DImode ? 4 : 0) | ||
| 175 | - + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); | ||
| 176 | - | ||
| 177 | - case SImode: | ||
| 178 | - return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); | ||
| 179 | - | ||
| 180 | - default: | ||
| 181 | - return 99; | ||
| 182 | - } | ||
| 183 | + total = mode == DImode ? COSTS_N_INSNS (1) : 0; | ||
| 184 | + total += thumb1_rtx_costs (XEXP (x, 0), GET_CODE (XEXP (x, 0)), code); | ||
| 185 | + | ||
| 186 | + if (mode == SImode) | ||
| 187 | + return total; | ||
| 188 | + | ||
| 189 | + if (arm_arch6) | ||
| 190 | + return total + COSTS_N_INSNS (1); | ||
| 191 | + | ||
| 192 | + /* Assume a two-shift sequence. Increase the cost slightly so | ||
| 193 | + we prefer actual shifts over an extend operation. */ | ||
| 194 | + return total + 1 + COSTS_N_INSNS (2); | ||
| 195 | |||
| 196 | default: | ||
| 197 | return 99; | ||
| 198 | @@ -7046,44 +7043,39 @@ | ||
| 199 | return false; | ||
| 200 | |||
| 201 | case SIGN_EXTEND: | ||
| 202 | - if (GET_MODE_CLASS (mode) == MODE_INT) | ||
| 203 | - { | ||
| 204 | - *total = 0; | ||
| 205 | - if (mode == DImode) | ||
| 206 | - *total += COSTS_N_INSNS (1); | ||
| 207 | - | ||
| 208 | - if (GET_MODE (XEXP (x, 0)) != SImode) | ||
| 209 | - { | ||
| 210 | - if (arm_arch6) | ||
| 211 | - { | ||
| 212 | - if (GET_CODE (XEXP (x, 0)) != MEM) | ||
| 213 | - *total += COSTS_N_INSNS (1); | ||
| 214 | - } | ||
| 215 | - else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) | ||
| 216 | - *total += COSTS_N_INSNS (2); | ||
| 217 | - } | ||
| 218 | - | ||
| 219 | - return false; | ||
| 220 | - } | ||
| 221 | - | ||
| 222 | - /* Fall through */ | ||
| 223 | case ZERO_EXTEND: | ||
| 224 | *total = 0; | ||
| 225 | if (GET_MODE_CLASS (mode) == MODE_INT) | ||
| 226 | { | ||
| 227 | + rtx op = XEXP (x, 0); | ||
| 228 | + enum machine_mode opmode = GET_MODE (op); | ||
| 229 | + | ||
| 230 | if (mode == DImode) | ||
| 231 | *total += COSTS_N_INSNS (1); | ||
| 232 | |||
| 233 | - if (GET_MODE (XEXP (x, 0)) != SImode) | ||
| 234 | + if (opmode != SImode) | ||
| 235 | { | ||
| 236 | - if (arm_arch6) | ||
| 237 | + if (MEM_P (op)) | ||
| 238 | { | ||
| 239 | - if (GET_CODE (XEXP (x, 0)) != MEM) | ||
| 240 | - *total += COSTS_N_INSNS (1); | ||
| 241 | + /* If !arm_arch4, we use one of the extendhisi2_mem | ||
| 242 | + or movhi_bytes patterns for HImode. For a QImode | ||
| 243 | + sign extension, we first zero-extend from memory | ||
| 244 | + and then perform a shift sequence. */ | ||
| 245 | + if (!arm_arch4 && (opmode != QImode || code == SIGN_EXTEND)) | ||
| 246 | + *total += COSTS_N_INSNS (2); | ||
| 247 | } | ||
| 248 | - else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) | ||
| 249 | - *total += COSTS_N_INSNS (GET_MODE (XEXP (x, 0)) == QImode ? | ||
| 250 | - 1 : 2); | ||
| 251 | + else if (arm_arch6) | ||
| 252 | + *total += COSTS_N_INSNS (1); | ||
| 253 | + | ||
| 254 | + /* We don't have the necessary insn, so we need to perform some | ||
| 255 | + other operation. */ | ||
| 256 | + else if (TARGET_ARM && code == ZERO_EXTEND && mode == QImode) | ||
| 257 | + /* An and with constant 255. */ | ||
| 258 | + *total += COSTS_N_INSNS (1); | ||
| 259 | + else | ||
| 260 | + /* A shift sequence. Increase costs slightly to avoid | ||
| 261 | + combining two shifts into an extend operation. */ | ||
| 262 | + *total += COSTS_N_INSNS (2) + 1; | ||
| 263 | } | ||
| 264 | |||
| 265 | return false; | ||
| 266 | @@ -7333,41 +7325,8 @@ | ||
| 267 | return false; | ||
| 268 | |||
| 269 | case SIGN_EXTEND: | ||
| 270 | - *total = 0; | ||
| 271 | - if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) < 4) | ||
| 272 | - { | ||
| 273 | - if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) | ||
| 274 | - *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); | ||
| 275 | - } | ||
| 276 | - if (mode == DImode) | ||
| 277 | - *total += COSTS_N_INSNS (1); | ||
| 278 | - return false; | ||
| 279 | - | ||
| 280 | case ZERO_EXTEND: | ||
| 281 | - *total = 0; | ||
| 282 | - if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) | ||
| 283 | - { | ||
| 284 | - switch (GET_MODE (XEXP (x, 0))) | ||
| 285 | - { | ||
| 286 | - case QImode: | ||
| 287 | - *total += COSTS_N_INSNS (1); | ||
| 288 | - break; | ||
| 289 | - | ||
| 290 | - case HImode: | ||
| 291 | - *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); | ||
| 292 | - | ||
| 293 | - case SImode: | ||
| 294 | - break; | ||
| 295 | - | ||
| 296 | - default: | ||
| 297 | - *total += COSTS_N_INSNS (2); | ||
| 298 | - } | ||
| 299 | - } | ||
| 300 | - | ||
| 301 | - if (mode == DImode) | ||
| 302 | - *total += COSTS_N_INSNS (1); | ||
| 303 | - | ||
| 304 | - return false; | ||
| 305 | + return arm_rtx_costs_1 (x, outer_code, total, 0); | ||
| 306 | |||
| 307 | case CONST_INT: | ||
| 308 | if (const_ok_for_arm (INTVAL (x))) | ||
| 309 | @@ -16898,11 +16857,11 @@ | ||
| 310 | |||
| 311 | case CC_Cmode: | ||
| 312 | switch (comp_code) | ||
| 313 | - { | ||
| 314 | - case LTU: return ARM_CS; | ||
| 315 | - case GEU: return ARM_CC; | ||
| 316 | - default: gcc_unreachable (); | ||
| 317 | - } | ||
| 318 | + { | ||
| 319 | + case LTU: return ARM_CS; | ||
| 320 | + case GEU: return ARM_CC; | ||
| 321 | + default: gcc_unreachable (); | ||
| 322 | + } | ||
| 323 | |||
| 324 | case CC_CZmode: | ||
| 325 | switch (comp_code) | ||
| 326 | @@ -20127,6 +20086,81 @@ | ||
| 327 | #endif | ||
| 328 | } | ||
| 329 | |||
| 330 | +/* Given the stack offsets and register mask in OFFSETS, decide how | ||
| 331 | + many additional registers to push instead of subtracting a constant | ||
| 332 | + from SP. For epilogues the principle is the same except we use pop. | ||
| 333 | + FOR_PROLOGUE indicates which we're generating. */ | ||
| 334 | +static int | ||
| 335 | +thumb1_extra_regs_pushed (arm_stack_offsets *offsets, bool for_prologue) | ||
| 336 | +{ | ||
| 337 | + HOST_WIDE_INT amount; | ||
| 338 | + unsigned long live_regs_mask = offsets->saved_regs_mask; | ||
| 339 | + /* Extract a mask of the ones we can give to the Thumb's push/pop | ||
| 340 | + instruction. */ | ||
| 341 | + unsigned long l_mask = live_regs_mask & (for_prologue ? 0x40ff : 0xff); | ||
| 342 | + /* Then count how many other high registers will need to be pushed. */ | ||
| 343 | + unsigned long high_regs_pushed = bit_count (live_regs_mask & 0x0f00); | ||
| 344 | + int n_free, reg_base; | ||
| 345 | + | ||
| 346 | + if (!for_prologue && frame_pointer_needed) | ||
| 347 | + amount = offsets->locals_base - offsets->saved_regs; | ||
| 348 | + else | ||
| 349 | + amount = offsets->outgoing_args - offsets->saved_regs; | ||
| 350 | + | ||
| 351 | + /* If the stack frame size is 512 exactly, we can save one load | ||
| 352 | + instruction, which should make this a win even when optimizing | ||
| 353 | + for speed. */ | ||
| 354 | + if (!optimize_size && amount != 512) | ||
| 355 | + return 0; | ||
| 356 | + | ||
| 357 | + /* Can't do this if there are high registers to push. */ | ||
| 358 | + if (high_regs_pushed != 0) | ||
| 359 | + return 0; | ||
| 360 | + | ||
| 361 | + /* Shouldn't do it in the prologue if no registers would normally | ||
| 362 | + be pushed at all. In the epilogue, also allow it if we'll have | ||
| 363 | + a pop insn for the PC. */ | ||
| 364 | + if (l_mask == 0 | ||
| 365 | + && (for_prologue | ||
| 366 | + || TARGET_BACKTRACE | ||
| 367 | + || (live_regs_mask & 1 << LR_REGNUM) == 0 | ||
| 368 | + || TARGET_INTERWORK | ||
| 369 | + || crtl->args.pretend_args_size != 0)) | ||
| 370 | + return 0; | ||
| 371 | + | ||
| 372 | + /* Don't do this if thumb_expand_prologue wants to emit instructions | ||
| 373 | + between the push and the stack frame allocation. */ | ||
| 374 | + if (for_prologue | ||
| 375 | + && ((flag_pic && arm_pic_register != INVALID_REGNUM) | ||
| 376 | + || (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0))) | ||
| 377 | + return 0; | ||
| 378 | + | ||
| 379 | + reg_base = 0; | ||
| 380 | + n_free = 0; | ||
| 381 | + if (!for_prologue) | ||
| 382 | + { | ||
| 383 | + reg_base = arm_size_return_regs () / UNITS_PER_WORD; | ||
| 384 | + live_regs_mask >>= reg_base; | ||
| 385 | + } | ||
| 386 | + | ||
| 387 | + while (reg_base + n_free < 8 && !(live_regs_mask & 1) | ||
| 388 | + && (for_prologue || call_used_regs[reg_base + n_free])) | ||
| 389 | + { | ||
| 390 | + live_regs_mask >>= 1; | ||
| 391 | + n_free++; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + if (n_free == 0) | ||
| 395 | + return 0; | ||
| 396 | + gcc_assert (amount / 4 * 4 == amount); | ||
| 397 | + | ||
| 398 | + if (amount >= 512 && (amount - n_free * 4) < 512) | ||
| 399 | + return (amount - 508) / 4; | ||
| 400 | + if (amount <= n_free * 4) | ||
| 401 | + return amount / 4; | ||
| 402 | + return 0; | ||
| 403 | +} | ||
| 404 | + | ||
| 405 | /* The bits which aren't usefully expanded as rtl. */ | ||
| 406 | const char * | ||
| 407 | thumb_unexpanded_epilogue (void) | ||
| 408 | @@ -20135,6 +20169,7 @@ | ||
| 409 | int regno; | ||
| 410 | unsigned long live_regs_mask = 0; | ||
| 411 | int high_regs_pushed = 0; | ||
| 412 | + int extra_pop; | ||
| 413 | int had_to_push_lr; | ||
| 414 | int size; | ||
| 415 | |||
| 416 | @@ -20154,6 +20189,13 @@ | ||
| 417 | the register is used to hold a return value. */ | ||
| 418 | size = arm_size_return_regs (); | ||
| 419 | |||
| 420 | + extra_pop = thumb1_extra_regs_pushed (offsets, false); | ||
| 421 | + if (extra_pop > 0) | ||
| 422 | + { | ||
| 423 | + unsigned long extra_mask = (1 << extra_pop) - 1; | ||
| 424 | + live_regs_mask |= extra_mask << (size / UNITS_PER_WORD); | ||
| 425 | + } | ||
| 426 | + | ||
| 427 | /* The prolog may have pushed some high registers to use as | ||
| 428 | work registers. e.g. the testsuite file: | ||
| 429 | gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c | ||
| 430 | @@ -20237,7 +20279,9 @@ | ||
| 431 | live_regs_mask); | ||
| 432 | |||
| 433 | /* We have either just popped the return address into the | ||
| 434 | - PC or it is was kept in LR for the entire function. */ | ||
| 435 | + PC or it is was kept in LR for the entire function. | ||
| 436 | + Note that thumb_pushpop has already called thumb_exit if the | ||
| 437 | + PC was in the list. */ | ||
| 438 | if (!had_to_push_lr) | ||
| 439 | thumb_exit (asm_out_file, LR_REGNUM); | ||
| 440 | } | ||
| 441 | @@ -20419,6 +20463,7 @@ | ||
| 442 | stack_pointer_rtx); | ||
| 443 | |||
| 444 | amount = offsets->outgoing_args - offsets->saved_regs; | ||
| 445 | + amount -= 4 * thumb1_extra_regs_pushed (offsets, true); | ||
| 446 | if (amount) | ||
| 447 | { | ||
| 448 | if (amount < 512) | ||
| 449 | @@ -20503,6 +20548,7 @@ | ||
| 450 | emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); | ||
| 451 | amount = offsets->locals_base - offsets->saved_regs; | ||
| 452 | } | ||
| 453 | + amount -= 4 * thumb1_extra_regs_pushed (offsets, false); | ||
| 454 | |||
| 455 | gcc_assert (amount >= 0); | ||
| 456 | if (amount) | ||
| 457 | @@ -20723,7 +20769,11 @@ | ||
| 458 | register. */ | ||
| 459 | else if ((l_mask & 0xff) != 0 | ||
| 460 | || (high_regs_pushed == 0 && l_mask)) | ||
| 461 | - thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask); | ||
| 462 | + { | ||
| 463 | + unsigned long mask = l_mask; | ||
| 464 | + mask |= (1 << thumb1_extra_regs_pushed (offsets, true)) - 1; | ||
| 465 | + thumb_pushpop (f, mask, 1, &cfa_offset, mask); | ||
| 466 | + } | ||
| 467 | |||
| 468 | if (high_regs_pushed) | ||
| 469 | { | ||
| 470 | |||
| 471 | === modified file 'gcc/config/arm/arm.md' | ||
| 472 | --- old/gcc/config/arm/arm.md 2010-08-25 16:22:17 +0000 | ||
| 473 | +++ new/gcc/config/arm/arm.md 2010-08-31 10:00:27 +0000 | ||
| 474 | @@ -150,6 +150,9 @@ | ||
| 475 | ; patterns that share the same RTL in both ARM and Thumb code. | ||
| 476 | (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) | ||
| 477 | |||
| 478 | +; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6. | ||
| 479 | +(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6"))) | ||
| 480 | + | ||
| 481 | ;; Operand number of an input operand that is shifted. Zero if the | ||
| 482 | ;; given instruction does not shift one of its input operands. | ||
| 483 | (define_attr "shift" "" (const_int 0)) | ||
| 484 | @@ -515,8 +518,8 @@ | ||
| 485 | (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) | ||
| 486 | (match_dup 1))) | ||
| 487 | (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) | ||
| 488 | - (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
| 489 | - (plus:SI (match_dup 4) (match_dup 5))))] | ||
| 490 | + (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5)) | ||
| 491 | + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
| 492 | " | ||
| 493 | { | ||
| 494 | operands[3] = gen_highpart (SImode, operands[0]); | ||
| 495 | @@ -543,10 +546,10 @@ | ||
| 496 | (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) | ||
| 497 | (match_dup 1))) | ||
| 498 | (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) | ||
| 499 | - (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
| 500 | - (plus:SI (ashiftrt:SI (match_dup 2) | ||
| 501 | + (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2) | ||
| 502 | (const_int 31)) | ||
| 503 | - (match_dup 4))))] | ||
| 504 | + (match_dup 4)) | ||
| 505 | + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
| 506 | " | ||
| 507 | { | ||
| 508 | operands[3] = gen_highpart (SImode, operands[0]); | ||
| 509 | @@ -572,8 +575,8 @@ | ||
| 510 | (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) | ||
| 511 | (match_dup 1))) | ||
| 512 | (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) | ||
| 513 | - (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
| 514 | - (plus:SI (match_dup 4) (const_int 0))))] | ||
| 515 | + (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0)) | ||
| 516 | + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
| 517 | " | ||
| 518 | { | ||
| 519 | operands[3] = gen_highpart (SImode, operands[0]); | ||
| 520 | @@ -861,24 +864,38 @@ | ||
| 521 | [(set_attr "conds" "set")] | ||
| 522 | ) | ||
| 523 | |||
| 524 | -(define_insn "*addsi3_carryin" | ||
| 525 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 526 | - (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
| 527 | - (plus:SI (match_operand:SI 1 "s_register_operand" "r") | ||
| 528 | - (match_operand:SI 2 "arm_rhs_operand" "rI"))))] | ||
| 529 | - "TARGET_32BIT" | ||
| 530 | - "adc%?\\t%0, %1, %2" | ||
| 531 | - [(set_attr "conds" "use")] | ||
| 532 | -) | ||
| 533 | - | ||
| 534 | -(define_insn "*addsi3_carryin_shift" | ||
| 535 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 536 | - (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
| 537 | - (plus:SI | ||
| 538 | - (match_operator:SI 2 "shift_operator" | ||
| 539 | - [(match_operand:SI 3 "s_register_operand" "r") | ||
| 540 | - (match_operand:SI 4 "reg_or_int_operand" "rM")]) | ||
| 541 | - (match_operand:SI 1 "s_register_operand" "r"))))] | ||
| 542 | +(define_code_iterator LTUGEU [ltu geu]) | ||
| 543 | +(define_code_attr cnb [(ltu "CC_C") (geu "CC")]) | ||
| 544 | +(define_code_attr optab [(ltu "ltu") (geu "geu")]) | ||
| 545 | + | ||
| 546 | +(define_insn "*addsi3_carryin_<optab>" | ||
| 547 | + [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 548 | + (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r") | ||
| 549 | + (match_operand:SI 2 "arm_rhs_operand" "rI")) | ||
| 550 | + (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))] | ||
| 551 | + "TARGET_32BIT" | ||
| 552 | + "adc%?\\t%0, %1, %2" | ||
| 553 | + [(set_attr "conds" "use")] | ||
| 554 | +) | ||
| 555 | + | ||
| 556 | +(define_insn "*addsi3_carryin_alt2_<optab>" | ||
| 557 | + [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 558 | + (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0)) | ||
| 559 | + (match_operand:SI 1 "s_register_operand" "%r")) | ||
| 560 | + (match_operand:SI 2 "arm_rhs_operand" "rI")))] | ||
| 561 | + "TARGET_32BIT" | ||
| 562 | + "adc%?\\t%0, %1, %2" | ||
| 563 | + [(set_attr "conds" "use")] | ||
| 564 | +) | ||
| 565 | + | ||
| 566 | +(define_insn "*addsi3_carryin_shift_<optab>" | ||
| 567 | + [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 568 | + (plus:SI (plus:SI | ||
| 569 | + (match_operator:SI 2 "shift_operator" | ||
| 570 | + [(match_operand:SI 3 "s_register_operand" "r") | ||
| 571 | + (match_operand:SI 4 "reg_or_int_operand" "rM")]) | ||
| 572 | + (match_operand:SI 1 "s_register_operand" "r")) | ||
| 573 | + (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))] | ||
| 574 | "TARGET_32BIT" | ||
| 575 | "adc%?\\t%0, %1, %3%S2" | ||
| 576 | [(set_attr "conds" "use") | ||
| 577 | @@ -887,36 +904,6 @@ | ||
| 578 | (const_string "alu_shift_reg")))] | ||
| 579 | ) | ||
| 580 | |||
| 581 | -(define_insn "*addsi3_carryin_alt1" | ||
| 582 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 583 | - (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") | ||
| 584 | - (match_operand:SI 2 "arm_rhs_operand" "rI")) | ||
| 585 | - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
| 586 | - "TARGET_32BIT" | ||
| 587 | - "adc%?\\t%0, %1, %2" | ||
| 588 | - [(set_attr "conds" "use")] | ||
| 589 | -) | ||
| 590 | - | ||
| 591 | -(define_insn "*addsi3_carryin_alt2" | ||
| 592 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 593 | - (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
| 594 | - (match_operand:SI 1 "s_register_operand" "r")) | ||
| 595 | - (match_operand:SI 2 "arm_rhs_operand" "rI")))] | ||
| 596 | - "TARGET_32BIT" | ||
| 597 | - "adc%?\\t%0, %1, %2" | ||
| 598 | - [(set_attr "conds" "use")] | ||
| 599 | -) | ||
| 600 | - | ||
| 601 | -(define_insn "*addsi3_carryin_alt3" | ||
| 602 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 603 | - (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
| 604 | - (match_operand:SI 2 "arm_rhs_operand" "rI")) | ||
| 605 | - (match_operand:SI 1 "s_register_operand" "r")))] | ||
| 606 | - "TARGET_32BIT" | ||
| 607 | - "adc%?\\t%0, %1, %2" | ||
| 608 | - [(set_attr "conds" "use")] | ||
| 609 | -) | ||
| 610 | - | ||
| 611 | (define_expand "incscc" | ||
| 612 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 613 | (plus:SI (match_operator:SI 2 "arm_comparison_operator" | ||
| 614 | @@ -1116,24 +1103,27 @@ | ||
| 615 | |||
| 616 | ; ??? Check Thumb-2 split length | ||
| 617 | (define_insn_and_split "*arm_subsi3_insn" | ||
| 618 | - [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r") | ||
| 619 | - (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n") | ||
| 620 | - (match_operand:SI 2 "s_register_operand" "r, r, r")))] | ||
| 621 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r") | ||
| 622 | + (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,!k,?n,r") | ||
| 623 | + (match_operand:SI 2 "reg_or_int_operand" "r,rI, r, r,?n")))] | ||
| 624 | "TARGET_32BIT" | ||
| 625 | "@ | ||
| 626 | rsb%?\\t%0, %2, %1 | ||
| 627 | sub%?\\t%0, %1, %2 | ||
| 628 | + sub%?\\t%0, %1, %2 | ||
| 629 | + # | ||
| 630 | #" | ||
| 631 | - "TARGET_32BIT | ||
| 632 | - && GET_CODE (operands[1]) == CONST_INT | ||
| 633 | - && !const_ok_for_arm (INTVAL (operands[1]))" | ||
| 634 | + "&& ((GET_CODE (operands[1]) == CONST_INT | ||
| 635 | + && !const_ok_for_arm (INTVAL (operands[1]))) | ||
| 636 | + || (GET_CODE (operands[2]) == CONST_INT | ||
| 637 | + && !const_ok_for_arm (INTVAL (operands[2]))))" | ||
| 638 | [(clobber (const_int 0))] | ||
| 639 | " | ||
| 640 | arm_split_constant (MINUS, SImode, curr_insn, | ||
| 641 | INTVAL (operands[1]), operands[0], operands[2], 0); | ||
| 642 | DONE; | ||
| 643 | " | ||
| 644 | - [(set_attr "length" "4,4,16") | ||
| 645 | + [(set_attr "length" "4,4,4,16,16") | ||
| 646 | (set_attr "predicable" "yes")] | ||
| 647 | ) | ||
| 648 | |||
| 649 | @@ -1165,6 +1155,19 @@ | ||
| 650 | [(set_attr "conds" "set")] | ||
| 651 | ) | ||
| 652 | |||
| 653 | +(define_insn "*subsi3_compare" | ||
| 654 | + [(set (reg:CC CC_REGNUM) | ||
| 655 | + (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I") | ||
| 656 | + (match_operand:SI 2 "arm_rhs_operand" "rI,r"))) | ||
| 657 | + (set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 658 | + (minus:SI (match_dup 1) (match_dup 2)))] | ||
| 659 | + "TARGET_32BIT" | ||
| 660 | + "@ | ||
| 661 | + sub%.\\t%0, %1, %2 | ||
| 662 | + rsb%.\\t%0, %2, %1" | ||
| 663 | + [(set_attr "conds" "set")] | ||
| 664 | +) | ||
| 665 | + | ||
| 666 | (define_expand "decscc" | ||
| 667 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 668 | (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") | ||
| 669 | @@ -4050,93 +4053,46 @@ | ||
| 670 | ) | ||
| 671 | |||
| 672 | (define_expand "zero_extendhisi2" | ||
| 673 | - [(set (match_dup 2) | ||
| 674 | - (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") | ||
| 675 | - (const_int 16))) | ||
| 676 | - (set (match_operand:SI 0 "s_register_operand" "") | ||
| 677 | - (lshiftrt:SI (match_dup 2) (const_int 16)))] | ||
| 678 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 679 | + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] | ||
| 680 | "TARGET_EITHER" | ||
| 681 | - " | ||
| 682 | - { | ||
| 683 | - if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM) | ||
| 684 | - { | ||
| 685 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
| 686 | - gen_rtx_ZERO_EXTEND (SImode, operands[1]))); | ||
| 687 | - DONE; | ||
| 688 | - } | ||
| 689 | - | ||
| 690 | - if (TARGET_ARM && GET_CODE (operands[1]) == MEM) | ||
| 691 | - { | ||
| 692 | - emit_insn (gen_movhi_bytes (operands[0], operands[1])); | ||
| 693 | - DONE; | ||
| 694 | - } | ||
| 695 | - | ||
| 696 | - if (!s_register_operand (operands[1], HImode)) | ||
| 697 | - operands[1] = copy_to_mode_reg (HImode, operands[1]); | ||
| 698 | - | ||
| 699 | - if (arm_arch6) | ||
| 700 | - { | ||
| 701 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
| 702 | - gen_rtx_ZERO_EXTEND (SImode, operands[1]))); | ||
| 703 | - DONE; | ||
| 704 | - } | ||
| 705 | - | ||
| 706 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
| 707 | - operands[2] = gen_reg_rtx (SImode); | ||
| 708 | - }" | ||
| 709 | -) | ||
| 710 | +{ | ||
| 711 | + if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1])) | ||
| 712 | + { | ||
| 713 | + emit_insn (gen_movhi_bytes (operands[0], operands[1])); | ||
| 714 | + DONE; | ||
| 715 | + } | ||
| 716 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
| 717 | + { | ||
| 718 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
| 719 | + rtx tmp = gen_reg_rtx (SImode); | ||
| 720 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); | ||
| 721 | + emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16))); | ||
| 722 | + DONE; | ||
| 723 | + } | ||
| 724 | +}) | ||
| 725 | + | ||
| 726 | +(define_split | ||
| 727 | + [(set (match_operand:SI 0 "register_operand" "") | ||
| 728 | + (zero_extend:SI (match_operand:HI 1 "register_operand" "l,m")))] | ||
| 729 | + "!TARGET_THUMB2 && !arm_arch6" | ||
| 730 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) | ||
| 731 | + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] | ||
| 732 | +{ | ||
| 733 | + operands[2] = gen_lowpart (SImode, operands[1]); | ||
| 734 | +}) | ||
| 735 | |||
| 736 | (define_insn "*thumb1_zero_extendhisi2" | ||
| 737 | - [(set (match_operand:SI 0 "register_operand" "=l") | ||
| 738 | - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | ||
| 739 | - "TARGET_THUMB1 && !arm_arch6" | ||
| 740 | - "* | ||
| 741 | - rtx mem = XEXP (operands[1], 0); | ||
| 742 | - | ||
| 743 | - if (GET_CODE (mem) == CONST) | ||
| 744 | - mem = XEXP (mem, 0); | ||
| 745 | - | ||
| 746 | - if (GET_CODE (mem) == LABEL_REF) | ||
| 747 | - return \"ldr\\t%0, %1\"; | ||
| 748 | - | ||
| 749 | - if (GET_CODE (mem) == PLUS) | ||
| 750 | - { | ||
| 751 | - rtx a = XEXP (mem, 0); | ||
| 752 | - rtx b = XEXP (mem, 1); | ||
| 753 | - | ||
| 754 | - /* This can happen due to bugs in reload. */ | ||
| 755 | - if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) | ||
| 756 | - { | ||
| 757 | - rtx ops[2]; | ||
| 758 | - ops[0] = operands[0]; | ||
| 759 | - ops[1] = a; | ||
| 760 | - | ||
| 761 | - output_asm_insn (\"mov %0, %1\", ops); | ||
| 762 | - | ||
| 763 | - XEXP (mem, 0) = operands[0]; | ||
| 764 | - } | ||
| 765 | - | ||
| 766 | - else if ( GET_CODE (a) == LABEL_REF | ||
| 767 | - && GET_CODE (b) == CONST_INT) | ||
| 768 | - return \"ldr\\t%0, %1\"; | ||
| 769 | - } | ||
| 770 | - | ||
| 771 | - return \"ldrh\\t%0, %1\"; | ||
| 772 | - " | ||
| 773 | - [(set_attr "length" "4") | ||
| 774 | - (set_attr "type" "load_byte") | ||
| 775 | - (set_attr "pool_range" "60")] | ||
| 776 | -) | ||
| 777 | - | ||
| 778 | -(define_insn "*thumb1_zero_extendhisi2_v6" | ||
| 779 | [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
| 780 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))] | ||
| 781 | - "TARGET_THUMB1 && arm_arch6" | ||
| 782 | + "TARGET_THUMB1" | ||
| 783 | "* | ||
| 784 | rtx mem; | ||
| 785 | |||
| 786 | - if (which_alternative == 0) | ||
| 787 | + if (which_alternative == 0 && arm_arch6) | ||
| 788 | return \"uxth\\t%0, %1\"; | ||
| 789 | + if (which_alternative == 0) | ||
| 790 | + return \"#\"; | ||
| 791 | |||
| 792 | mem = XEXP (operands[1], 0); | ||
| 793 | |||
| 794 | @@ -4170,20 +4126,25 @@ | ||
| 795 | |||
| 796 | return \"ldrh\\t%0, %1\"; | ||
| 797 | " | ||
| 798 | - [(set_attr "length" "2,4") | ||
| 799 | + [(set_attr_alternative "length" | ||
| 800 | + [(if_then_else (eq_attr "is_arch6" "yes") | ||
| 801 | + (const_int 2) (const_int 4)) | ||
| 802 | + (const_int 4)]) | ||
| 803 | (set_attr "type" "alu_shift,load_byte") | ||
| 804 | (set_attr "pool_range" "*,60")] | ||
| 805 | ) | ||
| 806 | |||
| 807 | (define_insn "*arm_zero_extendhisi2" | ||
| 808 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 809 | - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | ||
| 810 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 811 | + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | ||
| 812 | "TARGET_ARM && arm_arch4 && !arm_arch6" | ||
| 813 | - "ldr%(h%)\\t%0, %1" | ||
| 814 | - [(set_attr "type" "load_byte") | ||
| 815 | + "@ | ||
| 816 | + # | ||
| 817 | + ldr%(h%)\\t%0, %1" | ||
| 818 | + [(set_attr "type" "alu_shift,load_byte") | ||
| 819 | (set_attr "predicable" "yes") | ||
| 820 | - (set_attr "pool_range" "256") | ||
| 821 | - (set_attr "neg_pool_range" "244")] | ||
| 822 | + (set_attr "pool_range" "*,256") | ||
| 823 | + (set_attr "neg_pool_range" "*,244")] | ||
| 824 | ) | ||
| 825 | |||
| 826 | (define_insn "*arm_zero_extendhisi2_v6" | ||
| 827 | @@ -4213,50 +4174,49 @@ | ||
| 828 | [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 829 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] | ||
| 830 | "TARGET_EITHER" | ||
| 831 | - " | ||
| 832 | - if (!arm_arch6 && GET_CODE (operands[1]) != MEM) | ||
| 833 | - { | ||
| 834 | - if (TARGET_ARM) | ||
| 835 | - { | ||
| 836 | - emit_insn (gen_andsi3 (operands[0], | ||
| 837 | - gen_lowpart (SImode, operands[1]), | ||
| 838 | - GEN_INT (255))); | ||
| 839 | - } | ||
| 840 | - else /* TARGET_THUMB */ | ||
| 841 | - { | ||
| 842 | - rtx temp = gen_reg_rtx (SImode); | ||
| 843 | - rtx ops[3]; | ||
| 844 | - | ||
| 845 | - operands[1] = copy_to_mode_reg (QImode, operands[1]); | ||
| 846 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
| 847 | - | ||
| 848 | - ops[0] = temp; | ||
| 849 | - ops[1] = operands[1]; | ||
| 850 | - ops[2] = GEN_INT (24); | ||
| 851 | - | ||
| 852 | - emit_insn (gen_rtx_SET (VOIDmode, ops[0], | ||
| 853 | - gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); | ||
| 854 | - | ||
| 855 | - ops[0] = operands[0]; | ||
| 856 | - ops[1] = temp; | ||
| 857 | - ops[2] = GEN_INT (24); | ||
| 858 | - | ||
| 859 | - emit_insn (gen_rtx_SET (VOIDmode, ops[0], | ||
| 860 | - gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); | ||
| 861 | - } | ||
| 862 | - DONE; | ||
| 863 | - } | ||
| 864 | - " | ||
| 865 | -) | ||
| 866 | +{ | ||
| 867 | + if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM) | ||
| 868 | + { | ||
| 869 | + emit_insn (gen_andsi3 (operands[0], | ||
| 870 | + gen_lowpart (SImode, operands[1]), | ||
| 871 | + GEN_INT (255))); | ||
| 872 | + DONE; | ||
| 873 | + } | ||
| 874 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
| 875 | + { | ||
| 876 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
| 877 | + rtx tmp = gen_reg_rtx (SImode); | ||
| 878 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); | ||
| 879 | + emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24))); | ||
| 880 | + DONE; | ||
| 881 | + } | ||
| 882 | +}) | ||
| 883 | + | ||
| 884 | +(define_split | ||
| 885 | + [(set (match_operand:SI 0 "register_operand" "") | ||
| 886 | + (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] | ||
| 887 | + "!arm_arch6" | ||
| 888 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) | ||
| 889 | + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))] | ||
| 890 | +{ | ||
| 891 | + operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); | ||
| 892 | + if (TARGET_ARM) | ||
| 893 | + { | ||
| 894 | + emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255))); | ||
| 895 | + DONE; | ||
| 896 | + } | ||
| 897 | +}) | ||
| 898 | |||
| 899 | (define_insn "*thumb1_zero_extendqisi2" | ||
| 900 | - [(set (match_operand:SI 0 "register_operand" "=l") | ||
| 901 | - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] | ||
| 902 | + [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
| 903 | + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))] | ||
| 904 | "TARGET_THUMB1 && !arm_arch6" | ||
| 905 | - "ldrb\\t%0, %1" | ||
| 906 | - [(set_attr "length" "2") | ||
| 907 | - (set_attr "type" "load_byte") | ||
| 908 | - (set_attr "pool_range" "32")] | ||
| 909 | + "@ | ||
| 910 | + # | ||
| 911 | + ldrb\\t%0, %1" | ||
| 912 | + [(set_attr "length" "4,2") | ||
| 913 | + (set_attr "type" "alu_shift,load_byte") | ||
| 914 | + (set_attr "pool_range" "*,32")] | ||
| 915 | ) | ||
| 916 | |||
| 917 | (define_insn "*thumb1_zero_extendqisi2_v6" | ||
| 918 | @@ -4272,14 +4232,17 @@ | ||
| 919 | ) | ||
| 920 | |||
| 921 | (define_insn "*arm_zero_extendqisi2" | ||
| 922 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 923 | - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] | ||
| 924 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 925 | + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | ||
| 926 | "TARGET_ARM && !arm_arch6" | ||
| 927 | - "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" | ||
| 928 | - [(set_attr "type" "load_byte") | ||
| 929 | + "@ | ||
| 930 | + # | ||
| 931 | + ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" | ||
| 932 | + [(set_attr "length" "8,4") | ||
| 933 | + (set_attr "type" "alu_shift,load_byte") | ||
| 934 | (set_attr "predicable" "yes") | ||
| 935 | - (set_attr "pool_range" "4096") | ||
| 936 | - (set_attr "neg_pool_range" "4084")] | ||
| 937 | + (set_attr "pool_range" "*,4096") | ||
| 938 | + (set_attr "neg_pool_range" "*,4084")] | ||
| 939 | ) | ||
| 940 | |||
| 941 | (define_insn "*arm_zero_extendqisi2_v6" | ||
| 942 | @@ -4358,108 +4321,42 @@ | ||
| 943 | ) | ||
| 944 | |||
| 945 | (define_expand "extendhisi2" | ||
| 946 | - [(set (match_dup 2) | ||
| 947 | - (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") | ||
| 948 | - (const_int 16))) | ||
| 949 | - (set (match_operand:SI 0 "s_register_operand" "") | ||
| 950 | - (ashiftrt:SI (match_dup 2) | ||
| 951 | - (const_int 16)))] | ||
| 952 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 953 | + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] | ||
| 954 | "TARGET_EITHER" | ||
| 955 | - " | ||
| 956 | - { | ||
| 957 | - if (GET_CODE (operands[1]) == MEM) | ||
| 958 | - { | ||
| 959 | - if (TARGET_THUMB1) | ||
| 960 | - { | ||
| 961 | - emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); | ||
| 962 | - DONE; | ||
| 963 | - } | ||
| 964 | - else if (arm_arch4) | ||
| 965 | - { | ||
| 966 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
| 967 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
| 968 | - DONE; | ||
| 969 | - } | ||
| 970 | - } | ||
| 971 | - | ||
| 972 | - if (TARGET_ARM && GET_CODE (operands[1]) == MEM) | ||
| 973 | - { | ||
| 974 | - emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); | ||
| 975 | - DONE; | ||
| 976 | - } | ||
| 977 | - | ||
| 978 | - if (!s_register_operand (operands[1], HImode)) | ||
| 979 | - operands[1] = copy_to_mode_reg (HImode, operands[1]); | ||
| 980 | - | ||
| 981 | - if (arm_arch6) | ||
| 982 | - { | ||
| 983 | - if (TARGET_THUMB1) | ||
| 984 | - emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); | ||
| 985 | - else | ||
| 986 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
| 987 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
| 988 | - | ||
| 989 | - DONE; | ||
| 990 | - } | ||
| 991 | - | ||
| 992 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
| 993 | - operands[2] = gen_reg_rtx (SImode); | ||
| 994 | - }" | ||
| 995 | -) | ||
| 996 | - | ||
| 997 | -(define_insn "thumb1_extendhisi2" | ||
| 998 | - [(set (match_operand:SI 0 "register_operand" "=l") | ||
| 999 | - (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) | ||
| 1000 | - (clobber (match_scratch:SI 2 "=&l"))] | ||
| 1001 | - "TARGET_THUMB1 && !arm_arch6" | ||
| 1002 | - "* | ||
| 1003 | - { | ||
| 1004 | - rtx ops[4]; | ||
| 1005 | - rtx mem = XEXP (operands[1], 0); | ||
| 1006 | - | ||
| 1007 | - /* This code used to try to use 'V', and fix the address only if it was | ||
| 1008 | - offsettable, but this fails for e.g. REG+48 because 48 is outside the | ||
| 1009 | - range of QImode offsets, and offsettable_address_p does a QImode | ||
| 1010 | - address check. */ | ||
| 1011 | - | ||
| 1012 | - if (GET_CODE (mem) == CONST) | ||
| 1013 | - mem = XEXP (mem, 0); | ||
| 1014 | - | ||
| 1015 | - if (GET_CODE (mem) == LABEL_REF) | ||
| 1016 | - return \"ldr\\t%0, %1\"; | ||
| 1017 | - | ||
| 1018 | - if (GET_CODE (mem) == PLUS) | ||
| 1019 | - { | ||
| 1020 | - rtx a = XEXP (mem, 0); | ||
| 1021 | - rtx b = XEXP (mem, 1); | ||
| 1022 | - | ||
| 1023 | - if (GET_CODE (a) == LABEL_REF | ||
| 1024 | - && GET_CODE (b) == CONST_INT) | ||
| 1025 | - return \"ldr\\t%0, %1\"; | ||
| 1026 | - | ||
| 1027 | - if (GET_CODE (b) == REG) | ||
| 1028 | - return \"ldrsh\\t%0, %1\"; | ||
| 1029 | - | ||
| 1030 | - ops[1] = a; | ||
| 1031 | - ops[2] = b; | ||
| 1032 | - } | ||
| 1033 | - else | ||
| 1034 | - { | ||
| 1035 | - ops[1] = mem; | ||
| 1036 | - ops[2] = const0_rtx; | ||
| 1037 | - } | ||
| 1038 | - | ||
| 1039 | - gcc_assert (GET_CODE (ops[1]) == REG); | ||
| 1040 | - | ||
| 1041 | - ops[0] = operands[0]; | ||
| 1042 | - ops[3] = operands[2]; | ||
| 1043 | - output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); | ||
| 1044 | - return \"\"; | ||
| 1045 | - }" | ||
| 1046 | - [(set_attr "length" "4") | ||
| 1047 | - (set_attr "type" "load_byte") | ||
| 1048 | - (set_attr "pool_range" "1020")] | ||
| 1049 | -) | ||
| 1050 | +{ | ||
| 1051 | + if (TARGET_THUMB1) | ||
| 1052 | + { | ||
| 1053 | + emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); | ||
| 1054 | + DONE; | ||
| 1055 | + } | ||
| 1056 | + if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4) | ||
| 1057 | + { | ||
| 1058 | + emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); | ||
| 1059 | + DONE; | ||
| 1060 | + } | ||
| 1061 | + | ||
| 1062 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
| 1063 | + { | ||
| 1064 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
| 1065 | + rtx tmp = gen_reg_rtx (SImode); | ||
| 1066 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); | ||
| 1067 | + emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16))); | ||
| 1068 | + DONE; | ||
| 1069 | + } | ||
| 1070 | +}) | ||
| 1071 | + | ||
| 1072 | +(define_split | ||
| 1073 | + [(parallel | ||
| 1074 | + [(set (match_operand:SI 0 "register_operand" "") | ||
| 1075 | + (sign_extend:SI (match_operand:HI 1 "register_operand" ""))) | ||
| 1076 | + (clobber (match_scratch:SI 2 ""))])] | ||
| 1077 | + "!arm_arch6" | ||
| 1078 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) | ||
| 1079 | + (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] | ||
| 1080 | +{ | ||
| 1081 | + operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); | ||
| 1082 | +}) | ||
| 1083 | |||
| 1084 | ;; We used to have an early-clobber on the scratch register here. | ||
| 1085 | ;; However, there's a bug somewhere in reload which means that this | ||
| 1086 | @@ -4468,16 +4365,18 @@ | ||
| 1087 | ;; we try to verify the operands. Fortunately, we don't really need | ||
| 1088 | ;; the early-clobber: we can always use operand 0 if operand 2 | ||
| 1089 | ;; overlaps the address. | ||
| 1090 | -(define_insn "*thumb1_extendhisi2_insn_v6" | ||
| 1091 | +(define_insn "thumb1_extendhisi2" | ||
| 1092 | [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
| 1093 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m"))) | ||
| 1094 | (clobber (match_scratch:SI 2 "=X,l"))] | ||
| 1095 | - "TARGET_THUMB1 && arm_arch6" | ||
| 1096 | + "TARGET_THUMB1" | ||
| 1097 | "* | ||
| 1098 | { | ||
| 1099 | rtx ops[4]; | ||
| 1100 | rtx mem; | ||
| 1101 | |||
| 1102 | + if (which_alternative == 0 && !arm_arch6) | ||
| 1103 | + return \"#\"; | ||
| 1104 | if (which_alternative == 0) | ||
| 1105 | return \"sxth\\t%0, %1\"; | ||
| 1106 | |||
| 1107 | @@ -4525,7 +4424,10 @@ | ||
| 1108 | output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); | ||
| 1109 | return \"\"; | ||
| 1110 | }" | ||
| 1111 | - [(set_attr "length" "2,4") | ||
| 1112 | + [(set_attr_alternative "length" | ||
| 1113 | + [(if_then_else (eq_attr "is_arch6" "yes") | ||
| 1114 | + (const_int 2) (const_int 4)) | ||
| 1115 | + (const_int 4)]) | ||
| 1116 | (set_attr "type" "alu_shift,load_byte") | ||
| 1117 | (set_attr "pool_range" "*,1020")] | ||
| 1118 | ) | ||
| 1119 | @@ -4566,15 +4468,28 @@ | ||
| 1120 | }" | ||
| 1121 | ) | ||
| 1122 | |||
| 1123 | +(define_split | ||
| 1124 | + [(set (match_operand:SI 0 "register_operand" "") | ||
| 1125 | + (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] | ||
| 1126 | + "!arm_arch6" | ||
| 1127 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) | ||
| 1128 | + (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] | ||
| 1129 | +{ | ||
| 1130 | + operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); | ||
| 1131 | +}) | ||
| 1132 | + | ||
| 1133 | (define_insn "*arm_extendhisi2" | ||
| 1134 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 1135 | - (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | ||
| 1136 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 1137 | + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | ||
| 1138 | "TARGET_ARM && arm_arch4 && !arm_arch6" | ||
| 1139 | - "ldr%(sh%)\\t%0, %1" | ||
| 1140 | - [(set_attr "type" "load_byte") | ||
| 1141 | + "@ | ||
| 1142 | + # | ||
| 1143 | + ldr%(sh%)\\t%0, %1" | ||
| 1144 | + [(set_attr "length" "8,4") | ||
| 1145 | + (set_attr "type" "alu_shift,load_byte") | ||
| 1146 | (set_attr "predicable" "yes") | ||
| 1147 | - (set_attr "pool_range" "256") | ||
| 1148 | - (set_attr "neg_pool_range" "244")] | ||
| 1149 | + (set_attr "pool_range" "*,256") | ||
| 1150 | + (set_attr "neg_pool_range" "*,244")] | ||
| 1151 | ) | ||
| 1152 | |||
| 1153 | ;; ??? Check Thumb-2 pool range | ||
| 1154 | @@ -4636,46 +4551,45 @@ | ||
| 1155 | ) | ||
| 1156 | |||
| 1157 | (define_expand "extendqisi2" | ||
| 1158 | - [(set (match_dup 2) | ||
| 1159 | - (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "") | ||
| 1160 | - (const_int 24))) | ||
| 1161 | - (set (match_operand:SI 0 "s_register_operand" "") | ||
| 1162 | - (ashiftrt:SI (match_dup 2) | ||
| 1163 | - (const_int 24)))] | ||
| 1164 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 1165 | + (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))] | ||
| 1166 | "TARGET_EITHER" | ||
| 1167 | - " | ||
| 1168 | - { | ||
| 1169 | - if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM) | ||
| 1170 | - { | ||
| 1171 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
| 1172 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
| 1173 | - DONE; | ||
| 1174 | - } | ||
| 1175 | - | ||
| 1176 | - if (!s_register_operand (operands[1], QImode)) | ||
| 1177 | - operands[1] = copy_to_mode_reg (QImode, operands[1]); | ||
| 1178 | - | ||
| 1179 | - if (arm_arch6) | ||
| 1180 | - { | ||
| 1181 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
| 1182 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
| 1183 | - DONE; | ||
| 1184 | - } | ||
| 1185 | - | ||
| 1186 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
| 1187 | - operands[2] = gen_reg_rtx (SImode); | ||
| 1188 | - }" | ||
| 1189 | -) | ||
| 1190 | +{ | ||
| 1191 | + if (!arm_arch4 && MEM_P (operands[1])) | ||
| 1192 | + operands[1] = copy_to_mode_reg (QImode, operands[1]); | ||
| 1193 | + | ||
| 1194 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
| 1195 | + { | ||
| 1196 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
| 1197 | + rtx tmp = gen_reg_rtx (SImode); | ||
| 1198 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); | ||
| 1199 | + emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24))); | ||
| 1200 | + DONE; | ||
| 1201 | + } | ||
| 1202 | +}) | ||
| 1203 | + | ||
| 1204 | +(define_split | ||
| 1205 | + [(set (match_operand:SI 0 "register_operand" "") | ||
| 1206 | + (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] | ||
| 1207 | + "!arm_arch6" | ||
| 1208 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) | ||
| 1209 | + (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] | ||
| 1210 | +{ | ||
| 1211 | + operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); | ||
| 1212 | +}) | ||
| 1213 | |||
| 1214 | (define_insn "*arm_extendqisi" | ||
| 1215 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
| 1216 | - (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))] | ||
| 1217 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 1218 | + (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))] | ||
| 1219 | "TARGET_ARM && arm_arch4 && !arm_arch6" | ||
| 1220 | - "ldr%(sb%)\\t%0, %1" | ||
| 1221 | - [(set_attr "type" "load_byte") | ||
| 1222 | + "@ | ||
| 1223 | + # | ||
| 1224 | + ldr%(sb%)\\t%0, %1" | ||
| 1225 | + [(set_attr "length" "8,4") | ||
| 1226 | + (set_attr "type" "alu_shift,load_byte") | ||
| 1227 | (set_attr "predicable" "yes") | ||
| 1228 | - (set_attr "pool_range" "256") | ||
| 1229 | - (set_attr "neg_pool_range" "244")] | ||
| 1230 | + (set_attr "pool_range" "*,256") | ||
| 1231 | + (set_attr "neg_pool_range" "*,244")] | ||
| 1232 | ) | ||
| 1233 | |||
| 1234 | (define_insn "*arm_extendqisi_v6" | ||
| 1235 | @@ -4703,162 +4617,103 @@ | ||
| 1236 | (set_attr "predicable" "yes")] | ||
| 1237 | ) | ||
| 1238 | |||
| 1239 | -(define_insn "*thumb1_extendqisi2" | ||
| 1240 | - [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
| 1241 | - (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] | ||
| 1242 | - "TARGET_THUMB1 && !arm_arch6" | ||
| 1243 | - "* | ||
| 1244 | - { | ||
| 1245 | - rtx ops[3]; | ||
| 1246 | - rtx mem = XEXP (operands[1], 0); | ||
| 1247 | - | ||
| 1248 | - if (GET_CODE (mem) == CONST) | ||
| 1249 | - mem = XEXP (mem, 0); | ||
| 1250 | - | ||
| 1251 | - if (GET_CODE (mem) == LABEL_REF) | ||
| 1252 | - return \"ldr\\t%0, %1\"; | ||
| 1253 | - | ||
| 1254 | - if (GET_CODE (mem) == PLUS | ||
| 1255 | - && GET_CODE (XEXP (mem, 0)) == LABEL_REF) | ||
| 1256 | - return \"ldr\\t%0, %1\"; | ||
| 1257 | - | ||
| 1258 | - if (which_alternative == 0) | ||
| 1259 | - return \"ldrsb\\t%0, %1\"; | ||
| 1260 | - | ||
| 1261 | - ops[0] = operands[0]; | ||
| 1262 | - | ||
| 1263 | - if (GET_CODE (mem) == PLUS) | ||
| 1264 | - { | ||
| 1265 | - rtx a = XEXP (mem, 0); | ||
| 1266 | - rtx b = XEXP (mem, 1); | ||
| 1267 | - | ||
| 1268 | - ops[1] = a; | ||
| 1269 | - ops[2] = b; | ||
| 1270 | - | ||
| 1271 | - if (GET_CODE (a) == REG) | ||
| 1272 | - { | ||
| 1273 | - if (GET_CODE (b) == REG) | ||
| 1274 | - output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); | ||
| 1275 | - else if (REGNO (a) == REGNO (ops[0])) | ||
| 1276 | - { | ||
| 1277 | - output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); | ||
| 1278 | - output_asm_insn (\"lsl\\t%0, %0, #24\", ops); | ||
| 1279 | - output_asm_insn (\"asr\\t%0, %0, #24\", ops); | ||
| 1280 | - } | ||
| 1281 | - else | ||
| 1282 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
| 1283 | - } | ||
| 1284 | - else | ||
| 1285 | - { | ||
| 1286 | - gcc_assert (GET_CODE (b) == REG); | ||
| 1287 | - if (REGNO (b) == REGNO (ops[0])) | ||
| 1288 | - { | ||
| 1289 | - output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); | ||
| 1290 | - output_asm_insn (\"lsl\\t%0, %0, #24\", ops); | ||
| 1291 | - output_asm_insn (\"asr\\t%0, %0, #24\", ops); | ||
| 1292 | - } | ||
| 1293 | - else | ||
| 1294 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
| 1295 | - } | ||
| 1296 | - } | ||
| 1297 | - else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) | ||
| 1298 | - { | ||
| 1299 | - output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); | ||
| 1300 | - output_asm_insn (\"lsl\\t%0, %0, #24\", ops); | ||
| 1301 | - output_asm_insn (\"asr\\t%0, %0, #24\", ops); | ||
| 1302 | - } | ||
| 1303 | - else | ||
| 1304 | - { | ||
| 1305 | - ops[1] = mem; | ||
| 1306 | - ops[2] = const0_rtx; | ||
| 1307 | - | ||
| 1308 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
| 1309 | - } | ||
| 1310 | - return \"\"; | ||
| 1311 | - }" | ||
| 1312 | - [(set_attr "length" "2,6") | ||
| 1313 | - (set_attr "type" "load_byte,load_byte") | ||
| 1314 | - (set_attr "pool_range" "32,32")] | ||
| 1315 | -) | ||
| 1316 | - | ||
| 1317 | -(define_insn "*thumb1_extendqisi2_v6" | ||
| 1318 | +(define_split | ||
| 1319 | + [(set (match_operand:SI 0 "register_operand" "") | ||
| 1320 | + (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))] | ||
| 1321 | + "TARGET_THUMB1 && reload_completed" | ||
| 1322 | + [(set (match_dup 0) (match_dup 2)) | ||
| 1323 | + (set (match_dup 0) (sign_extend:SI (match_dup 3)))] | ||
| 1324 | +{ | ||
| 1325 | + rtx addr = XEXP (operands[1], 0); | ||
| 1326 | + | ||
| 1327 | + if (GET_CODE (addr) == CONST) | ||
| 1328 | + addr = XEXP (addr, 0); | ||
| 1329 | + | ||
| 1330 | + if (GET_CODE (addr) == PLUS | ||
| 1331 | + && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) | ||
| 1332 | + /* No split necessary. */ | ||
| 1333 | + FAIL; | ||
| 1334 | + | ||
| 1335 | + if (GET_CODE (addr) == PLUS | ||
| 1336 | + && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1))) | ||
| 1337 | + FAIL; | ||
| 1338 | + | ||
| 1339 | + if (reg_overlap_mentioned_p (operands[0], addr)) | ||
| 1340 | + { | ||
| 1341 | + rtx t = gen_lowpart (QImode, operands[0]); | ||
| 1342 | + emit_move_insn (t, operands[1]); | ||
| 1343 | + emit_insn (gen_thumb1_extendqisi2 (operands[0], t)); | ||
| 1344 | + DONE; | ||
| 1345 | + } | ||
| 1346 | + | ||
| 1347 | + if (REG_P (addr)) | ||
| 1348 | + { | ||
| 1349 | + addr = gen_rtx_PLUS (Pmode, addr, operands[0]); | ||
| 1350 | + operands[2] = const0_rtx; | ||
| 1351 | + } | ||
| 1352 | + else if (GET_CODE (addr) != PLUS) | ||
| 1353 | + FAIL; | ||
| 1354 | + else if (REG_P (XEXP (addr, 0))) | ||
| 1355 | + { | ||
| 1356 | + operands[2] = XEXP (addr, 1); | ||
| 1357 | + addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]); | ||
| 1358 | + } | ||
| 1359 | + else | ||
| 1360 | + { | ||
| 1361 | + operands[2] = XEXP (addr, 0); | ||
| 1362 | + addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]); | ||
| 1363 | + } | ||
| 1364 | + | ||
| 1365 | + operands[3] = change_address (operands[1], QImode, addr); | ||
| 1366 | +}) | ||
| 1367 | + | ||
| 1368 | +(define_peephole2 | ||
| 1369 | + [(set (match_operand:SI 0 "register_operand" "") | ||
| 1370 | + (plus:SI (match_dup 0) (match_operand 1 "const_int_operand"))) | ||
| 1371 | + (set (match_operand:SI 2 "register_operand" "") (const_int 0)) | ||
| 1372 | + (set (match_operand:SI 3 "register_operand" "") | ||
| 1373 | + (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))] | ||
| 1374 | + "TARGET_THUMB1 | ||
| 1375 | + && GET_CODE (XEXP (operands[4], 0)) == PLUS | ||
| 1376 | + && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0)) | ||
| 1377 | + && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1)) | ||
| 1378 | + && (peep2_reg_dead_p (3, operands[0]) | ||
| 1379 | + || rtx_equal_p (operands[0], operands[3])) | ||
| 1380 | + && (peep2_reg_dead_p (3, operands[2]) | ||
| 1381 | + || rtx_equal_p (operands[2], operands[3]))" | ||
| 1382 | + [(set (match_dup 2) (match_dup 1)) | ||
| 1383 | + (set (match_dup 3) (sign_extend:SI (match_dup 4)))] | ||
| 1384 | +{ | ||
| 1385 | + rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]); | ||
| 1386 | + operands[4] = change_address (operands[4], QImode, addr); | ||
| 1387 | +}) | ||
| 1388 | + | ||
| 1389 | +(define_insn "thumb1_extendqisi2" | ||
| 1390 | [(set (match_operand:SI 0 "register_operand" "=l,l,l") | ||
| 1391 | (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))] | ||
| 1392 | - "TARGET_THUMB1 && arm_arch6" | ||
| 1393 | - "* | ||
| 1394 | - { | ||
| 1395 | - rtx ops[3]; | ||
| 1396 | - rtx mem; | ||
| 1397 | - | ||
| 1398 | - if (which_alternative == 0) | ||
| 1399 | - return \"sxtb\\t%0, %1\"; | ||
| 1400 | - | ||
| 1401 | - mem = XEXP (operands[1], 0); | ||
| 1402 | - | ||
| 1403 | - if (GET_CODE (mem) == CONST) | ||
| 1404 | - mem = XEXP (mem, 0); | ||
| 1405 | - | ||
| 1406 | - if (GET_CODE (mem) == LABEL_REF) | ||
| 1407 | - return \"ldr\\t%0, %1\"; | ||
| 1408 | - | ||
| 1409 | - if (GET_CODE (mem) == PLUS | ||
| 1410 | - && GET_CODE (XEXP (mem, 0)) == LABEL_REF) | ||
| 1411 | - return \"ldr\\t%0, %1\"; | ||
| 1412 | - | ||
| 1413 | - if (which_alternative == 0) | ||
| 1414 | - return \"ldrsb\\t%0, %1\"; | ||
| 1415 | - | ||
| 1416 | - ops[0] = operands[0]; | ||
| 1417 | - | ||
| 1418 | - if (GET_CODE (mem) == PLUS) | ||
| 1419 | - { | ||
| 1420 | - rtx a = XEXP (mem, 0); | ||
| 1421 | - rtx b = XEXP (mem, 1); | ||
| 1422 | - | ||
| 1423 | - ops[1] = a; | ||
| 1424 | - ops[2] = b; | ||
| 1425 | - | ||
| 1426 | - if (GET_CODE (a) == REG) | ||
| 1427 | - { | ||
| 1428 | - if (GET_CODE (b) == REG) | ||
| 1429 | - output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); | ||
| 1430 | - else if (REGNO (a) == REGNO (ops[0])) | ||
| 1431 | - { | ||
| 1432 | - output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); | ||
| 1433 | - output_asm_insn (\"sxtb\\t%0, %0\", ops); | ||
| 1434 | - } | ||
| 1435 | - else | ||
| 1436 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
| 1437 | - } | ||
| 1438 | - else | ||
| 1439 | - { | ||
| 1440 | - gcc_assert (GET_CODE (b) == REG); | ||
| 1441 | - if (REGNO (b) == REGNO (ops[0])) | ||
| 1442 | - { | ||
| 1443 | - output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); | ||
| 1444 | - output_asm_insn (\"sxtb\\t%0, %0\", ops); | ||
| 1445 | - } | ||
| 1446 | - else | ||
| 1447 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
| 1448 | - } | ||
| 1449 | - } | ||
| 1450 | - else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) | ||
| 1451 | - { | ||
| 1452 | - output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); | ||
| 1453 | - output_asm_insn (\"sxtb\\t%0, %0\", ops); | ||
| 1454 | - } | ||
| 1455 | - else | ||
| 1456 | - { | ||
| 1457 | - ops[1] = mem; | ||
| 1458 | - ops[2] = const0_rtx; | ||
| 1459 | - | ||
| 1460 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
| 1461 | - } | ||
| 1462 | - return \"\"; | ||
| 1463 | - }" | ||
| 1464 | - [(set_attr "length" "2,2,4") | ||
| 1465 | - (set_attr "type" "alu_shift,load_byte,load_byte") | ||
| 1466 | - (set_attr "pool_range" "*,32,32")] | ||
| 1467 | + "TARGET_THUMB1" | ||
| 1468 | +{ | ||
| 1469 | + rtx addr; | ||
| 1470 | + | ||
| 1471 | + if (which_alternative == 0 && arm_arch6) | ||
| 1472 | + return "sxtb\\t%0, %1"; | ||
| 1473 | + if (which_alternative == 0) | ||
| 1474 | + return "#"; | ||
| 1475 | + | ||
| 1476 | + addr = XEXP (operands[1], 0); | ||
| 1477 | + if (GET_CODE (addr) == PLUS | ||
| 1478 | + && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) | ||
| 1479 | + return "ldrsb\\t%0, %1"; | ||
| 1480 | + | ||
| 1481 | + return "#"; | ||
| 1482 | +} | ||
| 1483 | + [(set_attr_alternative "length" | ||
| 1484 | + [(if_then_else (eq_attr "is_arch6" "yes") | ||
| 1485 | + (const_int 2) (const_int 4)) | ||
| 1486 | + (const_int 2) | ||
| 1487 | + (if_then_else (eq_attr "is_arch6" "yes") | ||
| 1488 | + (const_int 4) (const_int 6))]) | ||
| 1489 | + (set_attr "type" "alu_shift,load_byte,load_byte")] | ||
| 1490 | ) | ||
| 1491 | |||
| 1492 | (define_expand "extendsfdf2" | ||
| 1493 | @@ -6784,6 +6639,30 @@ | ||
| 1494 | operands[2] = force_reg (SImode, operands[2]); | ||
| 1495 | ") | ||
| 1496 | |||
| 1497 | +;; A pattern to recognize a special situation and optimize for it. | ||
| 1498 | +;; On the thumb, zero-extension from memory is preferrable to sign-extension | ||
| 1499 | +;; due to the available addressing modes. Hence, convert a signed comparison | ||
| 1500 | +;; with zero into an unsigned comparison with 127 if possible. | ||
| 1501 | +(define_expand "cbranchqi4" | ||
| 1502 | + [(set (pc) (if_then_else | ||
| 1503 | + (match_operator 0 "lt_ge_comparison_operator" | ||
| 1504 | + [(match_operand:QI 1 "memory_operand" "") | ||
| 1505 | + (match_operand:QI 2 "const0_operand" "")]) | ||
| 1506 | + (label_ref (match_operand 3 "" "")) | ||
| 1507 | + (pc)))] | ||
| 1508 | + "TARGET_THUMB1" | ||
| 1509 | +{ | ||
| 1510 | + rtx xops[4]; | ||
| 1511 | + xops[1] = gen_reg_rtx (SImode); | ||
| 1512 | + emit_insn (gen_zero_extendqisi2 (xops[1], operands[1])); | ||
| 1513 | + xops[2] = GEN_INT (127); | ||
| 1514 | + xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU, | ||
| 1515 | + VOIDmode, xops[1], xops[2]); | ||
| 1516 | + xops[3] = operands[3]; | ||
| 1517 | + emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3])); | ||
| 1518 | + DONE; | ||
| 1519 | +}) | ||
| 1520 | + | ||
| 1521 | (define_expand "cbranchsf4" | ||
| 1522 | [(set (pc) (if_then_else | ||
| 1523 | (match_operator 0 "arm_comparison_operator" | ||
| 1524 | @@ -6849,7 +6728,7 @@ | ||
| 1525 | }" | ||
| 1526 | ) | ||
| 1527 | |||
| 1528 | -(define_insn "*cbranchsi4_insn" | ||
| 1529 | +(define_insn "cbranchsi4_insn" | ||
| 1530 | [(set (pc) (if_then_else | ||
| 1531 | (match_operator 0 "arm_comparison_operator" | ||
| 1532 | [(match_operand:SI 1 "s_register_operand" "l,*h") | ||
| 1533 | @@ -6858,7 +6737,20 @@ | ||
| 1534 | (pc)))] | ||
| 1535 | "TARGET_THUMB1" | ||
| 1536 | "* | ||
| 1537 | - output_asm_insn (\"cmp\\t%1, %2\", operands); | ||
| 1538 | + rtx t = prev_nonnote_insn (insn); | ||
| 1539 | + if (t != NULL_RTX | ||
| 1540 | + && INSN_P (t) | ||
| 1541 | + && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn) | ||
| 1542 | + { | ||
| 1543 | + t = XEXP (SET_SRC (PATTERN (t)), 0); | ||
| 1544 | + if (!rtx_equal_p (XEXP (t, 0), operands[1]) | ||
| 1545 | + || !rtx_equal_p (XEXP (t, 1), operands[2])) | ||
| 1546 | + t = NULL_RTX; | ||
| 1547 | + } | ||
| 1548 | + else | ||
| 1549 | + t = NULL_RTX; | ||
| 1550 | + if (t == NULL_RTX) | ||
| 1551 | + output_asm_insn (\"cmp\\t%1, %2\", operands); | ||
| 1552 | |||
| 1553 | switch (get_attr_length (insn)) | ||
| 1554 | { | ||
| 1555 | @@ -7674,15 +7566,15 @@ | ||
| 1556 | (if_then_else | ||
| 1557 | (match_operator 4 "arm_comparison_operator" | ||
| 1558 | [(plus:SI | ||
| 1559 | - (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1") | ||
| 1560 | - (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ")) | ||
| 1561 | + (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1") | ||
| 1562 | + (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ")) | ||
| 1563 | (const_int 0)]) | ||
| 1564 | (label_ref (match_operand 5 "" "")) | ||
| 1565 | (pc))) | ||
| 1566 | (set | ||
| 1567 | (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m") | ||
| 1568 | (plus:SI (match_dup 2) (match_dup 3))) | ||
| 1569 | - (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))] | ||
| 1570 | + (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))] | ||
| 1571 | "TARGET_THUMB1 | ||
| 1572 | && (GET_CODE (operands[4]) == EQ | ||
| 1573 | || GET_CODE (operands[4]) == NE | ||
| 1574 | @@ -7692,8 +7584,7 @@ | ||
| 1575 | { | ||
| 1576 | rtx cond[3]; | ||
| 1577 | |||
| 1578 | - | ||
| 1579 | - cond[0] = (which_alternative < 3) ? operands[0] : operands[1]; | ||
| 1580 | + cond[0] = (which_alternative < 2) ? operands[0] : operands[1]; | ||
| 1581 | cond[1] = operands[2]; | ||
| 1582 | cond[2] = operands[3]; | ||
| 1583 | |||
| 1584 | @@ -7702,13 +7593,13 @@ | ||
| 1585 | else | ||
| 1586 | output_asm_insn (\"add\\t%0, %1, %2\", cond); | ||
| 1587 | |||
| 1588 | - if (which_alternative >= 3 | ||
| 1589 | + if (which_alternative >= 2 | ||
| 1590 | && which_alternative < 4) | ||
| 1591 | output_asm_insn (\"mov\\t%0, %1\", operands); | ||
| 1592 | else if (which_alternative >= 4) | ||
| 1593 | output_asm_insn (\"str\\t%1, %0\", operands); | ||
| 1594 | |||
| 1595 | - switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0)) | ||
| 1596 | + switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0)) | ||
| 1597 | { | ||
| 1598 | case 4: | ||
| 1599 | return \"b%d4\\t%l5\"; | ||
| 1600 | @@ -7722,7 +7613,7 @@ | ||
| 1601 | [(set (attr "far_jump") | ||
| 1602 | (if_then_else | ||
| 1603 | (ior (and (lt (symbol_ref ("which_alternative")) | ||
| 1604 | - (const_int 3)) | ||
| 1605 | + (const_int 2)) | ||
| 1606 | (eq_attr "length" "8")) | ||
| 1607 | (eq_attr "length" "10")) | ||
| 1608 | (const_string "yes") | ||
| 1609 | @@ -7730,7 +7621,7 @@ | ||
| 1610 | (set (attr "length") | ||
| 1611 | (if_then_else | ||
| 1612 | (lt (symbol_ref ("which_alternative")) | ||
| 1613 | - (const_int 3)) | ||
| 1614 | + (const_int 2)) | ||
| 1615 | (if_then_else | ||
| 1616 | (and (ge (minus (match_dup 5) (pc)) (const_int -250)) | ||
| 1617 | (le (minus (match_dup 5) (pc)) (const_int 256))) | ||
| 1618 | @@ -9483,41 +9374,117 @@ | ||
| 1619 | (set_attr "length" "4,8")] | ||
| 1620 | ) | ||
| 1621 | |||
| 1622 | -(define_insn "*compare_scc" | ||
| 1623 | +; A series of splitters for the compare_scc pattern below. Note that | ||
| 1624 | +; order is important. | ||
| 1625 | +(define_split | ||
| 1626 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 1627 | + (lt:SI (match_operand:SI 1 "s_register_operand" "") | ||
| 1628 | + (const_int 0))) | ||
| 1629 | + (clobber (reg:CC CC_REGNUM))] | ||
| 1630 | + "TARGET_32BIT && reload_completed" | ||
| 1631 | + [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))]) | ||
| 1632 | + | ||
| 1633 | +(define_split | ||
| 1634 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 1635 | + (ge:SI (match_operand:SI 1 "s_register_operand" "") | ||
| 1636 | + (const_int 0))) | ||
| 1637 | + (clobber (reg:CC CC_REGNUM))] | ||
| 1638 | + "TARGET_32BIT && reload_completed" | ||
| 1639 | + [(set (match_dup 0) (not:SI (match_dup 1))) | ||
| 1640 | + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))]) | ||
| 1641 | + | ||
| 1642 | +(define_split | ||
| 1643 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 1644 | + (eq:SI (match_operand:SI 1 "s_register_operand" "") | ||
| 1645 | + (const_int 0))) | ||
| 1646 | + (clobber (reg:CC CC_REGNUM))] | ||
| 1647 | + "TARGET_32BIT && reload_completed" | ||
| 1648 | + [(parallel | ||
| 1649 | + [(set (reg:CC CC_REGNUM) | ||
| 1650 | + (compare:CC (const_int 1) (match_dup 1))) | ||
| 1651 | + (set (match_dup 0) | ||
| 1652 | + (minus:SI (const_int 1) (match_dup 1)))]) | ||
| 1653 | + (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0)) | ||
| 1654 | + (set (match_dup 0) (const_int 0)))]) | ||
| 1655 | + | ||
| 1656 | +(define_split | ||
| 1657 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 1658 | + (ne:SI (match_operand:SI 1 "s_register_operand" "") | ||
| 1659 | + (match_operand:SI 2 "const_int_operand" ""))) | ||
| 1660 | + (clobber (reg:CC CC_REGNUM))] | ||
| 1661 | + "TARGET_32BIT && reload_completed" | ||
| 1662 | + [(parallel | ||
| 1663 | + [(set (reg:CC CC_REGNUM) | ||
| 1664 | + (compare:CC (match_dup 1) (match_dup 2))) | ||
| 1665 | + (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]) | ||
| 1666 | + (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0)) | ||
| 1667 | + (set (match_dup 0) (const_int 1)))] | ||
| 1668 | +{ | ||
| 1669 | + operands[3] = GEN_INT (-INTVAL (operands[2])); | ||
| 1670 | +}) | ||
| 1671 | + | ||
| 1672 | +(define_split | ||
| 1673 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
| 1674 | + (ne:SI (match_operand:SI 1 "s_register_operand" "") | ||
| 1675 | + (match_operand:SI 2 "arm_add_operand" ""))) | ||
| 1676 | + (clobber (reg:CC CC_REGNUM))] | ||
| 1677 | + "TARGET_32BIT && reload_completed" | ||
| 1678 | + [(parallel | ||
| 1679 | + [(set (reg:CC_NOOV CC_REGNUM) | ||
| 1680 | + (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2)) | ||
| 1681 | + (const_int 0))) | ||
| 1682 | + (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) | ||
| 1683 | + (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0)) | ||
| 1684 | + (set (match_dup 0) (const_int 1)))]) | ||
| 1685 | + | ||
| 1686 | +(define_insn_and_split "*compare_scc" | ||
| 1687 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 1688 | (match_operator:SI 1 "arm_comparison_operator" | ||
| 1689 | [(match_operand:SI 2 "s_register_operand" "r,r") | ||
| 1690 | (match_operand:SI 3 "arm_add_operand" "rI,L")])) | ||
| 1691 | (clobber (reg:CC CC_REGNUM))] | ||
| 1692 | - "TARGET_ARM" | ||
| 1693 | - "* | ||
| 1694 | - if (operands[3] == const0_rtx) | ||
| 1695 | - { | ||
| 1696 | - if (GET_CODE (operands[1]) == LT) | ||
| 1697 | - return \"mov\\t%0, %2, lsr #31\"; | ||
| 1698 | - | ||
| 1699 | - if (GET_CODE (operands[1]) == GE) | ||
| 1700 | - return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; | ||
| 1701 | - | ||
| 1702 | - if (GET_CODE (operands[1]) == EQ) | ||
| 1703 | - return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; | ||
| 1704 | - } | ||
| 1705 | - | ||
| 1706 | - if (GET_CODE (operands[1]) == NE) | ||
| 1707 | - { | ||
| 1708 | - if (which_alternative == 1) | ||
| 1709 | - return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; | ||
| 1710 | - return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; | ||
| 1711 | - } | ||
| 1712 | - if (which_alternative == 1) | ||
| 1713 | - output_asm_insn (\"cmn\\t%2, #%n3\", operands); | ||
| 1714 | - else | ||
| 1715 | - output_asm_insn (\"cmp\\t%2, %3\", operands); | ||
| 1716 | - return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; | ||
| 1717 | - " | ||
| 1718 | - [(set_attr "conds" "clob") | ||
| 1719 | - (set_attr "length" "12")] | ||
| 1720 | -) | ||
| 1721 | + "TARGET_32BIT" | ||
| 1722 | + "#" | ||
| 1723 | + "&& reload_completed" | ||
| 1724 | + [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3))) | ||
| 1725 | + (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0))) | ||
| 1726 | + (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))] | ||
| 1727 | +{ | ||
| 1728 | + rtx tmp1; | ||
| 1729 | + enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), | ||
| 1730 | + operands[2], operands[3]); | ||
| 1731 | + enum rtx_code rc = GET_CODE (operands[1]); | ||
| 1732 | + | ||
| 1733 | + tmp1 = gen_rtx_REG (mode, CC_REGNUM); | ||
| 1734 | + | ||
| 1735 | + operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); | ||
| 1736 | + if (mode == CCFPmode || mode == CCFPEmode) | ||
| 1737 | + rc = reverse_condition_maybe_unordered (rc); | ||
| 1738 | + else | ||
| 1739 | + rc = reverse_condition (rc); | ||
| 1740 | + operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); | ||
| 1741 | +}) | ||
| 1742 | + | ||
| 1743 | +;; Attempt to improve the sequence generated by the compare_scc splitters | ||
| 1744 | +;; not to use conditional execution. | ||
| 1745 | +(define_peephole2 | ||
| 1746 | + [(set (reg:CC CC_REGNUM) | ||
| 1747 | + (compare:CC (match_operand:SI 1 "register_operand" "") | ||
| 1748 | + (match_operand:SI 2 "arm_rhs_operand" ""))) | ||
| 1749 | + (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0)) | ||
| 1750 | + (set (match_operand:SI 0 "register_operand" "") (const_int 0))) | ||
| 1751 | + (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0)) | ||
| 1752 | + (set (match_dup 0) (const_int 1))) | ||
| 1753 | + (match_scratch:SI 3 "r")] | ||
| 1754 | + "TARGET_32BIT" | ||
| 1755 | + [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2))) | ||
| 1756 | + (parallel | ||
| 1757 | + [(set (reg:CC CC_REGNUM) | ||
| 1758 | + (compare:CC (const_int 0) (match_dup 3))) | ||
| 1759 | + (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))]) | ||
| 1760 | + (set (match_dup 0) | ||
| 1761 | + (plus:SI (plus:SI (match_dup 0) (match_dup 3)) | ||
| 1762 | + (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]) | ||
| 1763 | |||
| 1764 | (define_insn "*cond_move" | ||
| 1765 | [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | ||
| 1766 | |||
| 1767 | === modified file 'gcc/config/arm/predicates.md' | ||
| 1768 | --- old/gcc/config/arm/predicates.md 2010-08-31 09:40:16 +0000 | ||
| 1769 | +++ new/gcc/config/arm/predicates.md 2010-08-31 10:00:27 +0000 | ||
| 1770 | @@ -115,6 +115,10 @@ | ||
| 1771 | (and (match_code "const_int") | ||
| 1772 | (match_test "const_ok_for_arm (~INTVAL (op))"))) | ||
| 1773 | |||
| 1774 | +(define_predicate "const0_operand" | ||
| 1775 | + (and (match_code "const_int") | ||
| 1776 | + (match_test "INTVAL (op) == 0"))) | ||
| 1777 | + | ||
| 1778 | ;; Something valid on the RHS of an ARM data-processing instruction | ||
| 1779 | (define_predicate "arm_rhs_operand" | ||
| 1780 | (ior (match_operand 0 "s_register_operand") | ||
| 1781 | @@ -233,6 +237,9 @@ | ||
| 1782 | && (TARGET_FPA || TARGET_VFP)") | ||
| 1783 | (match_code "unordered,ordered,unlt,unle,unge,ungt")))) | ||
| 1784 | |||
| 1785 | +(define_special_predicate "lt_ge_comparison_operator" | ||
| 1786 | + (match_code "lt,ge")) | ||
| 1787 | + | ||
| 1788 | (define_special_predicate "minmax_operator" | ||
| 1789 | (and (match_code "smin,smax,umin,umax") | ||
| 1790 | (match_test "mode == GET_MODE (op)"))) | ||
| 1791 | |||
| 1792 | === modified file 'gcc/config/arm/thumb2.md' | ||
| 1793 | --- old/gcc/config/arm/thumb2.md 2010-08-31 09:40:16 +0000 | ||
| 1794 | +++ new/gcc/config/arm/thumb2.md 2010-08-31 10:00:27 +0000 | ||
| 1795 | @@ -599,42 +599,6 @@ | ||
| 1796 | (set_attr "length" "6,10")] | ||
| 1797 | ) | ||
| 1798 | |||
| 1799 | -(define_insn "*thumb2_compare_scc" | ||
| 1800 | - [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
| 1801 | - (match_operator:SI 1 "arm_comparison_operator" | ||
| 1802 | - [(match_operand:SI 2 "s_register_operand" "r,r") | ||
| 1803 | - (match_operand:SI 3 "arm_add_operand" "rI,L")])) | ||
| 1804 | - (clobber (reg:CC CC_REGNUM))] | ||
| 1805 | - "TARGET_THUMB2" | ||
| 1806 | - "* | ||
| 1807 | - if (operands[3] == const0_rtx) | ||
| 1808 | - { | ||
| 1809 | - if (GET_CODE (operands[1]) == LT) | ||
| 1810 | - return \"lsr\\t%0, %2, #31\"; | ||
| 1811 | - | ||
| 1812 | - if (GET_CODE (operands[1]) == GE) | ||
| 1813 | - return \"mvn\\t%0, %2\;lsr\\t%0, %0, #31\"; | ||
| 1814 | - | ||
| 1815 | - if (GET_CODE (operands[1]) == EQ) | ||
| 1816 | - return \"rsbs\\t%0, %2, #1\;it\\tcc\;movcc\\t%0, #0\"; | ||
| 1817 | - } | ||
| 1818 | - | ||
| 1819 | - if (GET_CODE (operands[1]) == NE) | ||
| 1820 | - { | ||
| 1821 | - if (which_alternative == 1) | ||
| 1822 | - return \"adds\\t%0, %2, #%n3\;it\\tne\;movne\\t%0, #1\"; | ||
| 1823 | - return \"subs\\t%0, %2, %3\;it\\tne\;movne\\t%0, #1\"; | ||
| 1824 | - } | ||
| 1825 | - if (which_alternative == 1) | ||
| 1826 | - output_asm_insn (\"cmn\\t%2, #%n3\", operands); | ||
| 1827 | - else | ||
| 1828 | - output_asm_insn (\"cmp\\t%2, %3\", operands); | ||
| 1829 | - return \"ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; | ||
| 1830 | - " | ||
| 1831 | - [(set_attr "conds" "clob") | ||
| 1832 | - (set_attr "length" "14")] | ||
| 1833 | -) | ||
| 1834 | - | ||
| 1835 | (define_insn "*thumb2_cond_move" | ||
| 1836 | [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | ||
| 1837 | (if_then_else:SI (match_operator 3 "equality_operator" | ||
| 1838 | |||
| 1839 | === added file 'gcc/testsuite/gcc.c-torture/execute/pr40657.c' | ||
| 1840 | --- old/gcc/testsuite/gcc.c-torture/execute/pr40657.c 1970-01-01 00:00:00 +0000 | ||
| 1841 | +++ new/gcc/testsuite/gcc.c-torture/execute/pr40657.c 2010-08-31 10:00:27 +0000 | ||
| 1842 | @@ -0,0 +1,23 @@ | ||
| 1843 | +/* Verify that that Thumb-1 epilogue size optimization does not clobber the | ||
| 1844 | + return value. */ | ||
| 1845 | + | ||
| 1846 | +long long v = 0x123456789abc; | ||
| 1847 | + | ||
| 1848 | +__attribute__((noinline)) void bar (int *x) | ||
| 1849 | +{ | ||
| 1850 | + asm volatile ("" : "=m" (x) ::); | ||
| 1851 | +} | ||
| 1852 | + | ||
| 1853 | +__attribute__((noinline)) long long foo() | ||
| 1854 | +{ | ||
| 1855 | + int x; | ||
| 1856 | + bar(&x); | ||
| 1857 | + return v; | ||
| 1858 | +} | ||
| 1859 | + | ||
| 1860 | +int main () | ||
| 1861 | +{ | ||
| 1862 | + if (foo () != v) | ||
| 1863 | + abort (); | ||
| 1864 | + exit (0); | ||
| 1865 | +} | ||
| 1866 | |||
| 1867 | === added file 'gcc/testsuite/gcc.target/arm/pr40657-1.c' | ||
| 1868 | --- old/gcc/testsuite/gcc.target/arm/pr40657-1.c 1970-01-01 00:00:00 +0000 | ||
| 1869 | +++ new/gcc/testsuite/gcc.target/arm/pr40657-1.c 2010-08-31 10:00:27 +0000 | ||
| 1870 | @@ -0,0 +1,13 @@ | ||
| 1871 | +/* { dg-options "-Os -march=armv5te -mthumb" } */ | ||
| 1872 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
| 1873 | +/* { dg-final { scan-assembler "pop.*r1.*pc" } } */ | ||
| 1874 | +/* { dg-final { scan-assembler-not "sub\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
| 1875 | +/* { dg-final { scan-assembler-not "add\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
| 1876 | + | ||
| 1877 | +extern void bar(int*); | ||
| 1878 | +int foo() | ||
| 1879 | +{ | ||
| 1880 | + int x; | ||
| 1881 | + bar(&x); | ||
| 1882 | + return x; | ||
| 1883 | +} | ||
| 1884 | |||
| 1885 | === added file 'gcc/testsuite/gcc.target/arm/pr40657-2.c' | ||
| 1886 | --- old/gcc/testsuite/gcc.target/arm/pr40657-2.c 1970-01-01 00:00:00 +0000 | ||
| 1887 | +++ new/gcc/testsuite/gcc.target/arm/pr40657-2.c 2010-08-31 10:00:27 +0000 | ||
| 1888 | @@ -0,0 +1,20 @@ | ||
| 1889 | +/* { dg-options "-Os -march=armv4t -mthumb" } */ | ||
| 1890 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
| 1891 | +/* { dg-final { scan-assembler-not "sub\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
| 1892 | +/* { dg-final { scan-assembler-not "add\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
| 1893 | + | ||
| 1894 | +/* Here, we test that if there's a pop of r[4567] in the epilogue, | ||
| 1895 | + add sp,sp,#12 is removed and replaced by three additional pops | ||
| 1896 | + of lower-numbered regs. */ | ||
| 1897 | + | ||
| 1898 | +extern void bar(int*); | ||
| 1899 | + | ||
| 1900 | +int t1, t2, t3, t4, t5; | ||
| 1901 | +int foo() | ||
| 1902 | +{ | ||
| 1903 | + int i,j,k,x = 0; | ||
| 1904 | + for (i = 0; i < t1; i++) | ||
| 1905 | + for (j = 0; j < t2; j++) | ||
| 1906 | + bar(&x); | ||
| 1907 | + return x; | ||
| 1908 | +} | ||
| 1909 | |||
| 1910 | === added file 'gcc/testsuite/gcc.target/arm/pr42172-1.c' | ||
| 1911 | --- old/gcc/testsuite/gcc.target/arm/pr42172-1.c 1970-01-01 00:00:00 +0000 | ||
| 1912 | +++ new/gcc/testsuite/gcc.target/arm/pr42172-1.c 2010-08-31 10:00:27 +0000 | ||
| 1913 | @@ -0,0 +1,19 @@ | ||
| 1914 | +/* { dg-options "-O2" } */ | ||
| 1915 | + | ||
| 1916 | +struct A { | ||
| 1917 | + unsigned int f1 : 3; | ||
| 1918 | + unsigned int f2 : 3; | ||
| 1919 | + unsigned int f3 : 1; | ||
| 1920 | + unsigned int f4 : 1; | ||
| 1921 | + | ||
| 1922 | +}; | ||
| 1923 | + | ||
| 1924 | +void init_A (struct A *this) | ||
| 1925 | +{ | ||
| 1926 | + this->f1 = 0; | ||
| 1927 | + this->f2 = 1; | ||
| 1928 | + this->f3 = 0; | ||
| 1929 | + this->f4 = 0; | ||
| 1930 | +} | ||
| 1931 | + | ||
| 1932 | +/* { dg-final { scan-assembler-times "ldr" 1 } } */ | ||
| 1933 | |||
| 1934 | === added file 'gcc/testsuite/gcc.target/arm/pr42835.c' | ||
| 1935 | --- old/gcc/testsuite/gcc.target/arm/pr42835.c 1970-01-01 00:00:00 +0000 | ||
| 1936 | +++ new/gcc/testsuite/gcc.target/arm/pr42835.c 2010-08-31 10:00:27 +0000 | ||
| 1937 | @@ -0,0 +1,12 @@ | ||
| 1938 | +/* { dg-do compile } */ | ||
| 1939 | +/* { dg-options "-mthumb -Os" } */ | ||
| 1940 | +/* { dg-require-effective-target arm_thumb2_ok } */ | ||
| 1941 | + | ||
| 1942 | +int foo(int *p, int i) | ||
| 1943 | +{ | ||
| 1944 | + return( (i < 0 && *p == 1) | ||
| 1945 | + || (i > 0 && *p == 2) ); | ||
| 1946 | +} | ||
| 1947 | + | ||
| 1948 | +/* { dg-final { scan-assembler-times "movne\[\\t \]*r.,\[\\t \]*#" 1 } } */ | ||
| 1949 | +/* { dg-final { scan-assembler-times "moveq\[\\t \]*r.,\[\\t \]*#" 1 } } */ | ||
| 1950 | |||
| 1951 | === added file 'gcc/testsuite/gcc.target/arm/thumb-cbranchqi.c' | ||
| 1952 | --- old/gcc/testsuite/gcc.target/arm/thumb-cbranchqi.c 1970-01-01 00:00:00 +0000 | ||
| 1953 | +++ new/gcc/testsuite/gcc.target/arm/thumb-cbranchqi.c 2010-08-31 10:00:27 +0000 | ||
| 1954 | @@ -0,0 +1,15 @@ | ||
| 1955 | +/* { dg-do compile } */ | ||
| 1956 | +/* { dg-options "-mthumb -Os" } */ | ||
| 1957 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
| 1958 | + | ||
| 1959 | +int ldrb(unsigned char* p) | ||
| 1960 | +{ | ||
| 1961 | + if (p[8] <= 0x7F) | ||
| 1962 | + return 2; | ||
| 1963 | + else | ||
| 1964 | + return 5; | ||
| 1965 | +} | ||
| 1966 | + | ||
| 1967 | + | ||
| 1968 | +/* { dg-final { scan-assembler "127" } } */ | ||
| 1969 | +/* { dg-final { scan-assembler "bhi" } } */ | ||
| 1970 | |||
| 1971 | === added file 'gcc/testsuite/gcc.target/arm/thumb-comparisons.c' | ||
| 1972 | --- old/gcc/testsuite/gcc.target/arm/thumb-comparisons.c 1970-01-01 00:00:00 +0000 | ||
| 1973 | +++ new/gcc/testsuite/gcc.target/arm/thumb-comparisons.c 2010-08-31 10:00:27 +0000 | ||
| 1974 | @@ -0,0 +1,18 @@ | ||
| 1975 | +/* { dg-do compile } */ | ||
| 1976 | +/* { dg-options "-mthumb -Os" } */ | ||
| 1977 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
| 1978 | + | ||
| 1979 | +int foo(char ch) | ||
| 1980 | +{ | ||
| 1981 | + switch (ch) { | ||
| 1982 | + case '-': | ||
| 1983 | + case '?': | ||
| 1984 | + case '/': | ||
| 1985 | + case 99: | ||
| 1986 | + return 1; | ||
| 1987 | + default: | ||
| 1988 | + return 0; | ||
| 1989 | + } | ||
| 1990 | +} | ||
| 1991 | + | ||
| 1992 | +/* { dg-final { scan-assembler-times "cmp\[\\t \]*r.,\[\\t \]*#63" 1 } } */ | ||
| 1993 | |||
| 1994 | === added file 'gcc/testsuite/gcc.target/arm/thumb-stackframe.c' | ||
| 1995 | --- old/gcc/testsuite/gcc.target/arm/thumb-stackframe.c 1970-01-01 00:00:00 +0000 | ||
| 1996 | +++ new/gcc/testsuite/gcc.target/arm/thumb-stackframe.c 2010-08-31 10:00:27 +0000 | ||
| 1997 | @@ -0,0 +1,13 @@ | ||
| 1998 | +/* { dg-do compile } */ | ||
| 1999 | +/* { dg-options "-mthumb -Os" } */ | ||
| 2000 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
| 2001 | + | ||
| 2002 | +extern void bar(int*); | ||
| 2003 | +int foo() | ||
| 2004 | +{ | ||
| 2005 | + int x; | ||
| 2006 | + bar(&x); | ||
| 2007 | + return x; | ||
| 2008 | +} | ||
| 2009 | + | ||
| 2010 | +/* { dg-final { scan-assembler-not "sub\[\\t \]*sp,\[\\t \]*sp," } } */ | ||
| 2011 | |||
