[gcc] Add clobber FLAGS_REG to NaCl indirect jumps

Compiler must know that NaCl indirect jump clobbers FLAGS register.

For call and return this is probably not important, as FLAGS is always clobbered by call.

For computed goto and switch, this IS important, so added explicit clobber.

TEST=very hard to reproduce, we only suspect this bug was the reason for LLVM miscompilation.

BUG=

Review URL: http://codereview.chromium.org/3892003
diff --git a/gcc/gcc/config/i386/i386.md b/gcc/gcc/config/i386/i386.md
index 8bced60..1192ce6 100644
--- a/gcc/gcc/config/i386/i386.md
+++ b/gcc/gcc/config/i386/i386.md
@@ -10025,10 +10025,10 @@
 
 (define_insn "nacljmp_indirectsi"
   [(set (pc) (unspec [(match_operand:SI 0 "register_operand" "r")]
-    UNSPEC_NACLJMP))]
-  ""
+    UNSPEC_NACLJMP))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_NACL"
 {
-  gcc_assert (TARGET_NACL);
   if (TARGET_64BIT)
     {
       return "nacljmp\t%0,%%r15";
@@ -10043,10 +10043,10 @@
 
 (define_insn "nacljmp_indirectdi"
   [(set (pc) (unspec [(match_operand:DI 0 "register_operand" "r")]
-    UNSPEC_NACLJMP))]
-  "TARGET_64BIT"
+    UNSPEC_NACLJMP))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT && TARGET_NACL"
 {
-  gcc_assert (TARGET_NACL);
   return "nacljmp\t%k0,%%r15";
 }
   [(set_attr "type" "ibr")
@@ -10055,10 +10055,10 @@
 (define_insn "nacljmp_tablesi"
   [(set (pc) (unspec [(match_operand:SI 0 "register_operand" "r")]
     UNSPEC_NACLJMP))
-   (use (label_ref (match_operand 1 "" "")))]
-  ""
+   (use (label_ref (match_operand 1 "" "")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_NACL"
 {
-  gcc_assert (TARGET_NACL);
   if (TARGET_64BIT)
     {
       return "nacljmp\t%0,%%r15";
@@ -10074,10 +10074,10 @@
 (define_insn "nacljmp_tabledi"
   [(set (pc) (unspec [(match_operand:DI 0 "register_operand" "r")]
     UNSPEC_NACLJMP))
-   (use (label_ref (match_operand 1 "" "")))]
-  "TARGET_64BIT"
+   (use (label_ref (match_operand 1 "" "")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT && TARGET_NACL"
 {
-  gcc_assert (TARGET_NACL);
   return "nacljmp\t%k0,%%r15";
 }
   [(set_attr "type" "ibr")
@@ -15270,21 +15270,24 @@
 (define_expand "indirect_jump"
   [(set (pc) (match_operand 0 "nonimmediate_operand" ""))]
   ""
-  "")
+{
+  if (TARGET_NACL)
+    {
+      enum machine_mode mode = GET_MODE (operands[0]);
+      rtx op0 = gen_rtx_UNSPEC (mode,
+				gen_rtvec (1, force_reg (mode, operands[0])),
+				UNSPEC_NACLJMP);
+      rtx set = gen_rtx_SET (VOIDmode, pc_rtx, op0);
+      rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clob)));
+      DONE;
+    }
+})
 
 (define_insn "*indirect_jump"
   [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm"))]
-  ""
-{
-  if (TARGET_64BIT)
-    {
-      return "nacljmp\t%k0,%%r15";
-    }
-  else
-    {
-      return "nacljmp\t%0";
-    }
-}
+  "!TARGET_NACL"
+  "jmp\t%A0"
   [(set_attr "type" "ibr")
    (set_attr "length_immediate" "0")])
 
@@ -15329,9 +15332,15 @@
   if (TARGET_NACL)
     {
       enum machine_mode mode = GET_MODE (operands[0]);
-      operands[0] = gen_rtx_UNSPEC (mode,
-                                    gen_rtvec (1, force_reg (mode, operands[0])),
-                                    UNSPEC_NACLJMP);
+      rtx op0 = gen_rtx_UNSPEC (mode,
+				gen_rtvec (1, force_reg (mode, operands[0])),
+				UNSPEC_NACLJMP);
+      rtx set = gen_rtx_SET (VOIDmode, pc_rtx, op0);
+      rtx use = gen_rtx_USE (VOIDmode, gen_rtx_LABEL_REF (Pmode, operands[1]));
+      rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
+					gen_rtvec (3, set, use, clob)));
+      DONE;
     }
 })