From 2a9a8f11ea1ecd04c3b9915ff77fc791c55632da Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 29 Mar 2016 12:06:20 +0200
Subject: [PATCH 2/2] Fix PR hsa/70402

gcc/ChangeLog:

2016-03-29  Martin Liska  <mliska@suse.cz>

	PR hsa/70402
	* hsa-gen.c (gen_hsa_insns_for_switch_stmt): Guard index
	value that is really in range handled by SBR instruction.
	* hsa-brig.c (emit_switch_insn): Do not emit unconditional
	jump.
	* hsa-dump.c (dump_hsa_insn_1): Do not dump default BB.
	* hsa.h (hsa_insn_sbr::m_default_bb): Remove field.
---
 gcc/hsa-brig.c |  4 ----
 gcc/hsa-dump.c |  3 ---
 gcc/hsa-gen.c  | 45 +++++++++++++++++++++++++++++++++++++++------
 gcc/hsa.h      |  3 ---
 4 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index 9b6c0b8..14c1d3f 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -1537,10 +1537,6 @@ emit_switch_insn (hsa_insn_sbr *sbr)
 
   brig_code.add (&repr, sizeof (repr));
   brig_insn_count++;
-
-  /* Emit jump to default label.  */
-  hsa_bb *hbb = hsa_bb_for_bb (sbr->m_default_bb);
-  emit_unconditional_jump (&hbb->m_label_ref);
 }
 
 /* Emit a HSA convert instruction and all necessary directives, schedule
diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c
index b69b34d..0885bc8 100644
--- a/gcc/hsa-dump.c
+++ b/gcc/hsa-dump.c
@@ -931,9 +931,6 @@ dump_hsa_insn_1 (FILE *f, hsa_insn_basic *insn, int *indent)
 	  if (i != sbr->m_jump_table.length () - 1)
 	    fprintf (f, ", ");
 	}
-
-      fprintf (f, "] /* default: BB %i */",
-	       hsa_bb_for_bb (sbr->m_default_bb)->m_index);
     }
   else if (is_a <hsa_insn_arg_block *> (insn))
     {
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 72eecf9..a8b868e 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -1530,7 +1530,7 @@ hsa_insn_br::operator new (size_t)
 
 hsa_insn_sbr::hsa_insn_sbr (hsa_op_reg *index, unsigned jump_count)
   : hsa_insn_basic (1, BRIG_OPCODE_SBR, BRIG_TYPE_B1, index),
-    m_width (BRIG_WIDTH_1), m_jump_table (vNULL), m_default_bb (NULL),
+    m_width (BRIG_WIDTH_1), m_jump_table (vNULL),
     m_label_code_list (new hsa_op_code_list (jump_count))
 {
 }
@@ -3398,11 +3398,49 @@ get_switch_size (gswitch *s)
 static void
 gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
 {
+  gimple_stmt_iterator it = gsi_for_stmt (s);
+  gsi_prev (&it);
+
+  /* Create preambule that verifies that index - lowest_label >= 0.  */
+  edge e = split_block (hbb->m_bb, gsi_stmt (it));
+  e->flags &= ~EDGE_FALLTHRU;
+  e->flags |= EDGE_TRUE_VALUE;
+
   function *func = DECL_STRUCT_FUNCTION (current_function_decl);
   tree index_tree = gimple_switch_index (s);
   tree lowest = get_switch_low (s);
+  tree highest = get_switch_high (s);
 
   hsa_op_reg *index = hsa_cfun->reg_for_gimple_ssa (index_tree);
+
+  hsa_op_reg *cmp1_reg = new hsa_op_reg (BRIG_TYPE_B1);
+  hsa_op_immed *cmp1_immed = new hsa_op_immed (lowest);
+  hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_GE, cmp1_reg->m_type,
+				      cmp1_reg, index, cmp1_immed));
+
+  hsa_op_reg *cmp2_reg = new hsa_op_reg (BRIG_TYPE_B1);
+  hsa_op_immed *cmp2_immed = new hsa_op_immed (highest);
+  hbb->append_insn (new hsa_insn_cmp (BRIG_COMPARE_LE, cmp2_reg->m_type,
+				      cmp2_reg, index, cmp2_immed));
+
+  hsa_op_reg *cmp_reg = new hsa_op_reg (BRIG_TYPE_B1);
+  hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_AND, cmp_reg->m_type,
+					cmp_reg, cmp1_reg, cmp2_reg));
+
+  hbb->append_insn (new hsa_insn_br (cmp_reg));
+
+  tree default_label = gimple_switch_default_label (s);
+  basic_block default_label_bb = label_to_block_fn (func,
+						    CASE_LABEL (default_label));
+
+  make_edge (e->src, default_label_bb, EDGE_FALSE_VALUE);
+
+  free_dominance_info (CDI_DOMINATORS);
+  calculate_dominance_info (CDI_DOMINATORS);
+
+  /* Basic block with the SBR instruction.  */
+  hbb = hsa_init_new_bb (e->dest);
+
   hsa_op_reg *sub_index = new hsa_op_reg (index->m_type);
   hbb->append_insn (new hsa_insn_basic (3, BRIG_OPCODE_SUB, sub_index->m_type,
 					sub_index, index,
@@ -3414,11 +3452,6 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
   unsigned HOST_WIDE_INT size = tree_to_uhwi (get_switch_size (s));
 
   hsa_insn_sbr *sbr = new hsa_insn_sbr (sub_index, size + 1);
-  tree default_label = gimple_switch_default_label (s);
-  basic_block default_label_bb = label_to_block_fn (func,
-						    CASE_LABEL (default_label));
-
-  sbr->m_default_bb = default_label_bb;
 
   /* Prepare array with default label destination.  */
   for (unsigned HOST_WIDE_INT i = 0; i <= size; i++)
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 1d6baab..1d55cef 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -562,9 +562,6 @@ public:
   /* Jump table.  */
   vec <basic_block> m_jump_table;
 
-  /* Default label basic block.  */
-  basic_block m_default_bb;
-
   /* Code list for label references.  */
   hsa_op_code_list *m_label_code_list;
 
-- 
2.7.1

