yann@1: [lightly edited to fit my patch directory - dank] yann@1: yann@1: From: kaz Kojima yann@1: Date: Sat, 09 Aug 2003 09:46:21 +0900 yann@1: To: dank@kegel.com yann@1: yann@1: Hi Dan, yann@1: yann@1: I've come back from the vacation and looked glibc string test yann@1: failures on sh4. This looks a gcc problem. gcc-3.3/3.4 doesn't yann@1: compile these tests correctly. The attached testcase aborts on yann@1: gcc-3.3/3.4 -O2 but exits normally gcc-3.2 and gcc-3.0. yann@1: The option -O2 is not essential but it makes the testcase small. yann@1: The failed string tests include the same pattern of the code with yann@1: f=random to generate ramdom strings but they get strings with yann@1: embedded NULL characters :-( yann@1: yann@1: ... yann@1: I've got a workaround below for this bug, though it might merely yann@1: paper over the real bug. Anyway, I'd like to send a PR for this. yann@1: yann@1: Regards, yann@1: kaz yann@1: -- yann@1: int val = 0xff00; yann@1: yann@1: int f (void) { return val; } yann@1: yann@1: unsigned char a[1]; yann@1: yann@1: void yann@1: foo (void) yann@1: { yann@1: a[0] = f () & 255; yann@1: yann@1: if (!a[0]) yann@1: a[0] = f () & 255; yann@1: yann@1: if (!a[0]) yann@1: a[0] = 1 + (f () & 127); yann@1: } yann@1: yann@1: int yann@1: main (int argc, char **argv) yann@1: { yann@1: foo (); yann@1: if (!a[0]) yann@1: abort (); yann@1: yann@1: return 0; yann@1: } yann@1: yann@1: -- yann@1: yann@1: diff -u3prN ORIG/gcc/gcc/config/sh/sh.c LOCAL/gcc/gcc/config/sh/sh.c yann@1: --- gcc/gcc/config/sh/sh.c.old Fri Aug 8 18:39:02 2003 yann@1: +++ gcc/gcc/config/sh/sh.c Fri Aug 8 22:31:02 2003 yann@1: @@ -6657,6 +6657,19 @@ arith_reg_dest (op, mode) yann@1: return arith_reg_operand (op, mode); yann@1: } yann@1: yann@1: +/* Like above, but for SImode compare destinations: forbid paradoxical yann@1: + subregs, because it would get the combiner confused. */ yann@1: +int yann@1: +arith_reg_cmp_dest (op, mode) yann@1: + rtx op; yann@1: + enum machine_mode mode; yann@1: +{ yann@1: + if (mode == SImode && GET_CODE (op) == SUBREG yann@1: + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 4) yann@1: + return 0; yann@1: + return arith_reg_operand (op, mode); yann@1: +} yann@1: + yann@1: int yann@1: int_gpr_dest (op, mode) yann@1: rtx op; yann@1: diff -u3prN ORIG/gcc/gcc/config/sh/sh.h LOCAL/gcc/gcc/config/sh/sh.h yann@1: --- gcc/gcc/config/sh/sh.h.old Fri Aug 8 18:39:02 2003 yann@1: +++ gcc/gcc/config/sh/sh.h Fri Aug 8 22:31:02 2003 yann@1: @@ -3365,6 +3365,7 @@ extern int rtx_equal_function_value_matt yann@1: {"and_operand", {SUBREG, REG, CONST_INT}}, \ yann@1: {"any_register_operand", {SUBREG, REG}}, \ yann@1: {"arith_operand", {SUBREG, REG, CONST_INT}}, \ yann@1: + {"arith_reg_cmp_dest", {SUBREG, REG}}, \ yann@1: {"arith_reg_dest", {SUBREG, REG}}, \ yann@1: {"arith_reg_operand", {SUBREG, REG}}, \ yann@1: {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}}, \ yann@1: yann@1: --- gcc-3.3/gcc/config/sh/sh.md.orig Tue Apr 15 10:06:10 2003 yann@1: +++ gcc-3.3/gcc/config/sh/sh.md Sat Aug 9 22:31:13 2003 yann@1: @@ -616,7 +616,7 @@ yann@1: yann@1: (define_insn "" yann@1: [(set (reg:SI T_REG) yann@1: - (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r") yann@1: + (eq:SI (and:SI (match_operand:SI 0 "arith_reg_cmp_dest" "z,r") yann@1: (match_operand:SI 1 "arith_operand" "L,r")) yann@1: (const_int 0)))] yann@1: "TARGET_SH1" yann@1: @@ -631,7 +631,7 @@ yann@1: yann@1: (define_insn "cmpeqsi_t" yann@1: [(set (reg:SI T_REG) yann@1: - (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r") yann@1: + (eq:SI (match_operand:SI 0 "arith_reg_cmp_dest" "r,z,r") yann@1: (match_operand:SI 1 "arith_operand" "N,rI,r")))] yann@1: "TARGET_SH1" yann@1: "@ yann@1: @@ -642,7 +642,7 @@ yann@1: yann@1: (define_insn "cmpgtsi_t" yann@1: [(set (reg:SI T_REG) yann@1: - (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") yann@1: + (gt:SI (match_operand:SI 0 "arith_reg_cmp_dest" "r,r") yann@1: (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] yann@1: "TARGET_SH1" yann@1: "@ yann@1: @@ -652,7 +652,7 @@ yann@1: yann@1: (define_insn "cmpgesi_t" yann@1: [(set (reg:SI T_REG) yann@1: - (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") yann@1: + (ge:SI (match_operand:SI 0 "arith_reg_cmp_dest" "r,r") yann@1: (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] yann@1: "TARGET_SH1" yann@1: "@ yann@1: @@ -666,7 +666,7 @@ yann@1: yann@1: (define_insn "cmpgeusi_t" yann@1: [(set (reg:SI T_REG) yann@1: - (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") yann@1: + (geu:SI (match_operand:SI 0 "arith_reg_cmp_dest" "r") yann@1: (match_operand:SI 1 "arith_reg_operand" "r")))] yann@1: "TARGET_SH1" yann@1: "cmp/hs %1,%0" yann@1: @@ -674,7 +674,7 @@ yann@1: yann@1: (define_insn "cmpgtusi_t" yann@1: [(set (reg:SI T_REG) yann@1: - (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") yann@1: + (gtu:SI (match_operand:SI 0 "arith_reg_cmp_dest" "r") yann@1: (match_operand:SI 1 "arith_reg_operand" "r")))] yann@1: "TARGET_SH1" yann@1: "cmp/hi %1,%0"