summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/cmm/CmmContFlowOpt.hs13
-rw-r--r--testsuite/tests/cmm/opt/Makefile6
-rw-r--r--testsuite/tests/cmm/opt/T15188.cmm6
-rw-r--r--testsuite/tests/cmm/opt/T15188.stdout1
-rw-r--r--testsuite/tests/cmm/opt/all.T3
5 files changed, 25 insertions, 4 deletions
diff --git a/compiler/cmm/CmmContFlowOpt.hs b/compiler/cmm/CmmContFlowOpt.hs
index 9f091da8c2..146c4f3019 100644
--- a/compiler/cmm/CmmContFlowOpt.hs
+++ b/compiler/cmm/CmmContFlowOpt.hs
@@ -254,8 +254,8 @@ blockConcat splitting_procs g@CmmGraph { g_entry = entry_id }
-- unconditional jump to a block that can be shortcut.
| Nothing <- callContinuation_maybe last
= let oldSuccs = successors last
- newSuccs = successors swapcond_last
- in ( mapInsert bid (blockJoinTail head swapcond_last) blocks
+ newSuccs = successors rewrite_last
+ in ( mapInsert bid (blockJoinTail head rewrite_last) blocks
, shortcut_map
, if oldSuccs == newSuccs
then backEdges
@@ -283,8 +283,13 @@ blockConcat splitting_procs g@CmmGraph { g_entry = entry_id }
Just b | Just dest <- canShortcut b -> dest
_otherwise -> l
- -- See Note [Invert Cmm conditionals]
- swapcond_last
+ rewrite_last
+ -- Sometimes we can get rid of the conditional completely.
+ | CmmCondBranch _cond t f _l <- shortcut_last
+ , t == f
+ = CmmBranch t
+
+ -- See Note [Invert Cmm conditionals]
| CmmCondBranch cond t f l <- shortcut_last
, hasOnePredecessor t -- inverting will make t a fallthrough
, likelyTrue l || (numPreds f > 1)
diff --git a/testsuite/tests/cmm/opt/Makefile b/testsuite/tests/cmm/opt/Makefile
new file mode 100644
index 0000000000..3c462ec0c0
--- /dev/null
+++ b/testsuite/tests/cmm/opt/Makefile
@@ -0,0 +1,6 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+T15188:
+ '$(TEST_HC)' $(TEST_HC_OPTS) -c -O -ddump-cmm-cps -dsuppress-all T15188.cmm | grep if ; echo $$?
diff --git a/testsuite/tests/cmm/opt/T15188.cmm b/testsuite/tests/cmm/opt/T15188.cmm
new file mode 100644
index 0000000000..59df92d78e
--- /dev/null
+++ b/testsuite/tests/cmm/opt/T15188.cmm
@@ -0,0 +1,6 @@
+func(bits64 r2) {
+ foo:
+ if (r2 == 0) { goto bar; } else { goto bar; }
+ bar:
+ return (1);
+}
diff --git a/testsuite/tests/cmm/opt/T15188.stdout b/testsuite/tests/cmm/opt/T15188.stdout
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/testsuite/tests/cmm/opt/T15188.stdout
@@ -0,0 +1 @@
+1
diff --git a/testsuite/tests/cmm/opt/all.T b/testsuite/tests/cmm/opt/all.T
new file mode 100644
index 0000000000..b2c0f5f8e7
--- /dev/null
+++ b/testsuite/tests/cmm/opt/all.T
@@ -0,0 +1,3 @@
+# Verify that we optimize away conditional branches which always jump
+# to the same target.
+test('T15188', normal, run_command, ['$MAKE -s --no-print-directory T15188'])