From 72b415c58668d3bd757fb8ec3be70302c339d544 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Sun, 30 Nov 2008 19:19:06 +0000 Subject: [PATCH] re PR target/38287 (segfault at -O2 -fPIC -mcpu=v8) PR target/38287 * config/sparc/sparc.md (divsi3 expander): Remove constraints. (divsi3_sp32): Add new alternative with 'K' for operand #2. (cmp_sdiv_cc_set): Factor common string. (udivsi3_sp32): Add new alternative with 'K' for operand #2. Add TARGET_V9 case. (cmp_udiv_cc_set): Factor common string. From-SVN: r142295 --- gcc/ChangeLog | 10 +++ gcc/config/sparc/sparc.md | 122 ++++++++++++++++++++++++------------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/opt/reload3.C | 39 ++++++++++++ 4 files changed, 132 insertions(+), 43 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/reload3.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ea9a94e..5602b5a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2008-11-30 Eric Botcazou + + PR target/38287 + * config/sparc/sparc.md (divsi3 expander): Remove constraints. + (divsi3_sp32): Add new alternative with 'K' for operand #2. + (cmp_sdiv_cc_set): Factor common string. + (udivsi3_sp32): Add new alternative with 'K' for operand #2. + Add TARGET_V9 case. + (cmp_udiv_cc_set): Factor common string. + 2008-11-30 John David Anglin PR middle-end/38283 diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 7dadde2..0a82e89 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -4895,14 +4895,11 @@ [(set_attr "type" "multi") (set_attr "length" "2")]) -;; The V8 architecture specifies that there must be 3 instructions between -;; a Y register write and a use of it for correct results. - (define_expand "divsi3" - [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r") - (div:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "input_operand" "rI,m"))) - (clobber (match_scratch:SI 3 "=&r,&r"))])] + [(parallel [(set (match_operand:SI 0 "register_operand" "") + (div:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "input_operand" ""))) + (clobber (match_scratch:SI 3 ""))])] "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" { if (TARGET_ARCH64) @@ -4915,24 +4912,40 @@ } }) +;; The V8 architecture specifies that there must be at least 3 instructions +;; between a write to the Y register and a use of it for correct results. +;; We try to fill one of them with a simple constant or a memory load. + (define_insn "divsi3_sp32" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (div:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "input_operand" "rI,m"))) - (clobber (match_scratch:SI 3 "=&r,&r"))] - "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) - && TARGET_ARCH32" -{ - if (which_alternative == 0) - if (TARGET_V9) - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdiv\t%1, %2, %0"; - else - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0"; - else - if (TARGET_V9) - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tsdiv\t%1, %3, %0"; - else - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0"; + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (div:SI (match_operand:SI 1 "register_operand" "r,r,r") + (match_operand:SI 2 "input_operand" "rI,K,m"))) + (clobber (match_scratch:SI 3 "=&r,&r,&r"))] + "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32" +{ + output_asm_insn ("sra\t%1, 31, %3", operands); + output_asm_insn ("wr\t%3, 0, %%y", operands); + + switch (which_alternative) + { + case 0: + if (TARGET_V9) + return "sdiv\t%1, %2, %0"; + else + return "nop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0"; + case 1: + if (TARGET_V9) + return "sethi\t%%hi(%a2), %3\n\tsdiv\t%1, %3, %0"; + else + return "sethi\t%%hi(%a2), %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0"; + case 2: + if (TARGET_V9) + return "ld\t%2, %3\n\tsdiv\t%1, %3, %0"; + else + return "ld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0"; + default: + gcc_unreachable (); + } } [(set_attr "type" "multi") (set (attr "length") @@ -4967,10 +4980,13 @@ (clobber (match_scratch:SI 3 "=&r"))] "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" { + output_asm_insn ("sra\t%1, 31, %3", operands); + output_asm_insn ("wr\t%3, 0, %%y", operands); + if (TARGET_V9) - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdivcc\t%1, %2, %0"; + return "sdivcc\t%1, %2, %0"; else - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0"; + return "nop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0"; } [(set_attr "type" "multi") (set (attr "length") @@ -4985,29 +5001,48 @@ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" "") -;; The V8 architecture specifies that there must be 3 instructions between -;; a Y register write and a use of it for correct results. +;; The V8 architecture specifies that there must be at least 3 instructions +;; between a write to the Y register and a use of it for correct results. +;; We try to fill one of them with a simple constant or a memory load. (define_insn "udivsi3_sp32" - [(set (match_operand:SI 0 "register_operand" "=r,&r,&r") - (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,m") - (match_operand:SI 2 "input_operand" "rI,m,r")))] - "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) - && TARGET_ARCH32" + [(set (match_operand:SI 0 "register_operand" "=r,&r,&r,&r") + (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,r,m") + (match_operand:SI 2 "input_operand" "rI,K,m,r")))] + "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32" { - output_asm_insn ("wr\t%%g0, %%g0, %%y", operands); + output_asm_insn ("wr\t%%g0, 0, %%y", operands); + switch (which_alternative) { - default: - return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0"; + case 0: + if (TARGET_V9) + return "udiv\t%1, %2, %0"; + else + return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0"; case 1: - return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0"; + if (TARGET_V9) + return "sethi\t%%hi(%a2), %0\n\tudiv\t%1, %0, %0"; + else + return "sethi\t%%hi(%a2), %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0"; case 2: - return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0"; + if (TARGET_V9) + return "ld\t%2, %0\n\tudiv\t%1, %0, %0"; + else + return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0"; + case 3: + if (TARGET_V9) + return "ld\t%1, %0\n\tudiv\t%0, %2, %0"; + else + return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0"; + default: + gcc_unreachable (); } } [(set_attr "type" "multi") - (set_attr "length" "5")]) + (set (attr "length") + (if_then_else (eq_attr "isa" "v9") + (const_int 3) (const_int 5)))]) (define_insn "udivsi3_sp64" [(set (match_operand:SI 0 "register_operand" "=r") @@ -5033,13 +5068,14 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") (udiv:SI (match_dup 1) (match_dup 2)))] - "TARGET_V8 - || TARGET_DEPRECATED_V8_INSNS" + "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" { + output_asm_insn ("wr\t%%g0, 0, %%y", operands); + if (TARGET_V9) - return "wr\t%%g0, %%g0, %%y\n\tudivcc\t%1, %2, %0"; + return "udivcc\t%1, %2, %0"; else - return "wr\t%%g0, %%g0, %%y\n\tnop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0"; + return "nop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0"; } [(set_attr "type" "multi") (set (attr "length") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fa68f2e..cd0d6c4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-11-30 Eric Botcazou + + * g++.dg/opt/reload3.C: New test. + 2008-11-30 Paul Thomas PR fortran/35824 diff --git a/gcc/testsuite/g++.dg/opt/reload3.C b/gcc/testsuite/g++.dg/opt/reload3.C new file mode 100644 index 0000000..12f3e66 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/reload3.C @@ -0,0 +1,39 @@ +// PR target/38287 +// { dg-do run } +// { dg-options "-O2 -mcpu=v8 -fPIC" { target { { sparc*-*-* } && { ilp32 && fpic } } } } + +#include + +class QTime +{ +public: + explicit QTime(int ms = 0) : ds(ms) {} + static QTime currentTime() { return QTime(); } + QTime addMSecs(int ms) const; + int msecs() const { return ds; } +private: + unsigned ds; +}; + +static const unsigned MSECS_PER_DAY = 86400000; + +QTime QTime::addMSecs(int ms) const +{ + QTime t; + if ( ms < 0 ) { + // % not well-defined for -ve, but / is. + int negdays = (MSECS_PER_DAY-ms) / MSECS_PER_DAY; + t.ds = ((int)ds + ms + negdays*MSECS_PER_DAY) + % MSECS_PER_DAY; + } else { + t.ds = ((int)ds + ms) % MSECS_PER_DAY; + } + return t; +} + +int main() +{ + if (QTime(1).addMSecs(1).msecs() != 2) + abort (); + return 0; +} -- 2.7.4