https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116066
Bug ID: 116066
Summary: ext-dce + uncommitted LoongArch patch breaks libcpp
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: xry111 at gcc dot gnu.org
Target Milestone: ---
Separated from PR115877 comment 14.
With my LoongArch patch to remove redundant sign-extension after 32-bit
shifting (not submitted yet, heavily reduced and crafted to highlight the part
triggering the issue and ease debugging but the change should be legal):
diff --git a/gcc/config/loongarch/loongarch.md
b/gcc/config/loongarch/loongarch.md
index bc09712bce7..979d7d333d4 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -2985,7 +2985,27 @@ (define_expand "cpymemsi"
;;
;; ....................
-(define_insn "<optab><mode>3"
+(define_code_attr gate [(ashiftrt "0") (ashift "0") (lshiftrt "getenv
(\"SHOW_THE_BUG\")")])
+
+(define_expand "<optab><mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (any_shift:GPR (match_operand:GPR 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+{
+ if (<gate> && TARGET_64BIT && <MODE>mode == SImode)
+ {
+ rtx t = gen_reg_rtx (DImode);
+ emit_insn (gen_<optab>si3_extend (t, operands[1], operands[2]));
+ t = gen_lowpart (SImode, t);
+ SUBREG_PROMOTED_VAR_P (t) = 1;
+ SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+ emit_move_insn (operands[0], t);
+ DONE;
+ }
+})
+
+(define_insn "*<optab><mode>3"
[(set (match_operand:GPR 0 "register_operand" "=r")
(any_shift:GPR (match_operand:GPR 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
@@ -3000,7 +3020,7 @@ (define_insn "<optab><mode>3"
[(set_attr "type" "shift")
(set_attr "mode" "<MODE>")])
-(define_insn "*<optab>si3_extend"
+(define_insn "<optab>si3_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI
(any_shift:SI (match_operand:SI 1 "register_operand" "r")
stage 2 libcpp is broken and behaving stupidly:
$ ../gcc/configure --enable-languages=c,c++ --with-system-zlib
--disable-fixincludes
... ...
$ make STAGE1_{C,CXX}FLAGS="-O2 -g" -j32 stage2-bubble
... ...
$ cat > t.c << EOF
#if -0
#endif
EOF
$ ./gcc/cc1 -E t.c
... (fine)
$ rm libcpp/expr.o # rebuild this with SHOW_THE_BUG trigger
$ SHOW_THE_BUG=1 make STAGE1_{C,CXX}FLAGS="-O2 -g" -j32 stage2-bubble
... ...
$ ./gcc/cc1 -E t.c
t.c:1:7: warning: integer overflow in preprocessor expression
1 | #if -0
| ^
It seems ext-dce is doing something wrong. Before it:
(insn 109 107 114 14 (set (reg:DI 91 [ num$17 ])
(zero_extend:DI (subreg:QI (reg:SI 133) 0)))
"../../gcc/libcpp/expr.cc":1968:17 discrim 6 129 {zero_extendqidi2}
(expr_list:REG_DEAD (reg:SI 133)
(nil)))
(insn 3470 1252 1253 145 (set (reg:DI 1528)
(reg:DI 294 [ num$17 ])) "../../gcc/libcpp/expr.cc":1565:33 158
{*movdi_64bit}
(nil))
(insn 1257 1256 134 145 (set (reg:DI 329 [ prephitmp_444 ])
(zero_extend:DI (subreg/s/v:QI (reg:DI 1528) 0)))
"../../gcc/libcpp/expr.cc":1681:22 129 {zero_extendqidi2}
(expr_list:REG_DEAD (reg:DI 1528)
(nil)))
During ext_dce:
Processing insn:
109: r91:DI=zero_extend(r133:SI#0)
REG_DEAD r133:SI
Trying to simplify pattern:
(zero_extend:DI (subreg:QI (reg:SI 133) 0))
rescanning insn with uid = 109.
Successfully transformed to:
(subreg:DI (reg:SI 133) 0)
So insn 109 becomes:
(insn 109 107 114 14 (set (reg:DI 91 [ num$17 ])
(subreg:DI (reg:SI 133) 0)) "../../gcc/libcpp/expr.cc":1968:17 discrim
6 158 {*movdi_64bit}
(expr_list:REG_DEAD (reg:SI 133)
(nil)))
But insn 3470 and 1257 are not changed (i.e. in 1257 the SUBREG_PROMOTED_VAR_P,
printed as "/s" isn't removed). Subsequently the combine pass optimizes 1257
to:
(insn 1257 1256 134 145 (set (reg:DI 329 [ prephitmp_444 ])
(reg:DI 294 [ num$17 ])) "../../gcc/libcpp/expr.cc":1681:22 158
{*movdi_64bit}
(expr_list:REG_DEAD (reg:DI 294 [ num$17 ])
(nil)))
and triggers the bug.