summaryrefslogtreecommitdiff
path: root/gcc/final.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/final.c')
-rw-r--r--gcc/final.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/gcc/final.c b/gcc/final.c
index 0938e221d5e..454ab6c71f5 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1980,6 +1980,18 @@ final (first, file, optimize, prescan)
max_uid = INSN_UID (insn);
if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
line_note_exists[NOTE_LINE_NUMBER (insn)] = 1;
+#ifdef HAVE_cc0
+ /* If CC tracking across branches is enabled, record the insn which
+ jumps to each branch only reached from one place. */
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ rtx lab = JUMP_LABEL (insn);
+ if (lab && LABEL_NUSES (lab) == 1)
+ {
+ LABEL_REFS (lab) = insn;
+ }
+ }
+#endif
}
/* Initialize insn_eh_region table if eh is being used. */
@@ -2283,7 +2295,30 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
ASM_OUTPUT_ALIGN (file, align);
#endif
}
+#ifdef HAVE_cc0
CC_STATUS_INIT;
+ /* If this label is reached from only one place, set the condition
+ codes from the instruction just before the branch. */
+ if (LABEL_NUSES (insn) == 1)
+ {
+ rtx jump = LABEL_REFS (insn);
+ rtx barrier = prev_nonnote_insn (insn);
+ rtx prev;
+ /* If the LABEL_REFS field of this label has been set to point
+ at a branch, the predecessor of the branch is a regular
+ insn, and that branch is the only way to reach this label,
+ set the condition codes based on the branch and its
+ predecessor. */
+ if (barrier && GET_CODE (barrier) == BARRIER
+ && jump && GET_CODE (jump) == JUMP_INSN
+ && (prev = prev_nonnote_insn (jump))
+ && GET_CODE (prev) == INSN)
+ {
+ NOTICE_UPDATE_CC (PATTERN (prev), prev);
+ NOTICE_UPDATE_CC (PATTERN (jump), jump);
+ }
+ }
+#endif
if (prescan > 0)
break;
new_block = 1;