cbranchsi4

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I try to add cbranchhi4 and cbranchsi4 to a new machine description
for a 16 bit target.

I have no problem with cbranchhi4. But cbranchsi4 does not work in
other optimization modes than O0.

Here is the code I include to implement cbranchsi4:

_____________________target.md_____________________________________
(define_expand "cbranchsi4"
  [(set (pc)
        (if_then_else (match_operator 0 "any_comparison_operator"
                                      [(match_operand:SI 1
"nonimmediate_operand" "")
                                       (match_operand:SI 2
"general_operand" "")])
                      (label_ref (match_operand 3 "" ""))
                      (pc)))]
  ""
  {
    tam16_expand_cbranchsi4(operands);
    DONE;
  })
__________________________________________________________________
_____________________target.c_______________________________________
  void
tam16_expand_cbranchsi4 (rtx ops[])
{
  enum rtx_code code = GET_CODE (ops[0]);
  enum rtx_code code1 = EQ;
  enum rtx_code code2 = EQ;
  enum rtx_code code3 = EQ;

  rtx op1lo = simplify_gen_subreg(HImode,ops[1],SImode,0);
  rtx op2lo = simplify_gen_subreg(HImode,ops[2],SImode,0);
  rtx op1hi = simplify_gen_subreg(HImode,ops[1],SImode,2);
  rtx op2hi = simplify_gen_subreg(HImode,ops[2],SImode,2);

  rtx branch1 = NULL;
  rtx branch2 = NULL;
  rtx branch3 = NULL;

  rtx condition1 = NULL;
  rtx condition2 = NULL;
  rtx condition3 = NULL;

  rtx nojump_label = gen_label_rtx ();
  rtx jump_label = ops[3];

  printf ("[ ops ]\n");
  debug_rtx (ops[0]);
  debug_rtx (ops[1]);
  debug_rtx (ops[2]);
  debug_rtx (ops[3]);

  switch (code)
  {
    default:
      gcc_unreachable ();
      break;

    case EQ:
      code1 = NE;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = EQ;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case NE:
      code1 = NE;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code3 = NE;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;
    case LT:
      code1 = LT;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = NE;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = LTU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case LE:
      code1 = LT;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = GT;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = LEU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case GT:
      code1 = GT;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = NE;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = GTU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case GE:
      code1 = GT;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = LT;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = GEU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case LTU:
      code1 = LTU;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = NE;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = LTU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case LEU:
      code1 = LTU;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = GTU;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = LEU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case GTU:
      code1 = GTU;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = NE;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = GTU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;

    case GEU:
      code1 = GTU;
      branch1 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      code2 = LTU;
      branch2 = gen_rtx_LABEL_REF (VOIDmode, nojump_label);
      code3 = GEU;
      branch3 = gen_rtx_LABEL_REF (VOIDmode, jump_label);
      break;
  }

  // Compute the condition rtxs
  condition1 = gen_rtx_fmt_ee (code1, VOIDmode, cc0_rtx, const0_rtx);
  condition2 = gen_rtx_fmt_ee (code2, VOIDmode, cc0_rtx, const0_rtx);
  condition3 = gen_rtx_fmt_ee (code3, VOIDmode, cc0_rtx, const0_rtx);

  gcc_assert (condition1 != NULL);
  gcc_assert (condition2 != NULL);
  gcc_assert (condition3 != NULL);
  gcc_assert (op1lo != NULL);
  gcc_assert (op1lo != NULL);
  gcc_assert (op2hi != NULL);
  gcc_assert (op2hi != NULL);

  // Compare MSB
  emit_insn (gen_rtx_SET (VOIDmode,
                          cc0_rtx,
                          gen_rtx_COMPARE (HImode, op1hi, op2hi)));

  // Branch 1
  if (branch1 != NULL)
  {
    emit_jump_insn (gen_rtx_SET (VOIDmode,
                                 pc_rtx,
                                 gen_rtx_IF_THEN_ELSE (VOIDmode,
                                                       condition1,
                                                       branch1,
                                                       pc_rtx)));
  }

  // Branch 2
  if (branch2 != NULL)
  {
    emit_jump_insn (gen_rtx_SET (VOIDmode,
                                 pc_rtx,
                                 gen_rtx_IF_THEN_ELSE (VOIDmode,
                                                       condition2,
                                                       branch2,
                                                       pc_rtx)));
  }

  // Compare LSB
  emit_insn (gen_rtx_SET (VOIDmode,
                          cc0_rtx,
                          gen_rtx_COMPARE (HImode, op1lo, op2lo)));

  // Branch 3
  if (branch3 != NULL)
  {
    emit_jump_insn (gen_rtx_SET (VOIDmode,
                                 pc_rtx,
                                 gen_rtx_IF_THEN_ELSE (VOIDmode,
                                                       condition3,
                                                       branch3,
                                                       pc_rtx)));
  }

  // No jump, continue here ...
  emit_label (nojump_label);
}
__________________________________________________________________


And here is the result of the compilation of a program with long
(SImode) comparisons with -O1:

$ /home/guest1/tam16/libexec/gcc/tam16/4.3.3/cc1 -quiet main.c -quiet
-dumpbase main.c -auxbase main -O1 -o main.s
[ ops ]
(ge:SI (reg:SI 17 [ aa.1 ])
    (reg:SI 16 [ bb.2 ]))
(reg:SI 17 [ aa.1 ])
(reg:SI 16 [ bb.2 ])
(code_label 0 0 0 3 "" [0 uses])
main.c: In function ‘main’:
main.c:283: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.


After debugging with GDB, I found out that equiv_constant is called
with a null rtx as argument:

Program received signal SIGSEGV, Segmentation fault.
equiv_constant (x=0x0) at ../../gcc-4.3.3/gcc/cse.c:3603
3603      if (REG_P (x)
(gdb) bt
#0  equiv_constant (x=0x0) at ../../gcc-4.3.3/gcc/cse.c:3603
#1  0x0836bf37 in fold_rtx (x=0xb7c35c30, insn=0xb7c3baa0) at
../../gcc-4.3.3/gcc/cse.c:3056
#2  0x0836c1b5 in fold_rtx (x=0xb7c36de0, insn=0xb7c3baa0) at
../../gcc-4.3.3/gcc/cse.c:3055
#3  0x0836ee14 in cse_insn (insn=0xb7c3baa0, libcall_insn=0x0) at
../../gcc-4.3.3/gcc/cse.c:4294
#4  0x0837256b in cse_main (f=0xb7c9f780, nregs=25) at
../../gcc-4.3.3/gcc/cse.c:6093
#5  0x08372daa in rest_of_handle_cse () at ../../gcc-4.3.3/gcc/cse.c:7022
#6  0x081a25e4 in execute_one_pass (pass=0x8499cc0) at
../../gcc-4.3.3/gcc/passes.c:1122
#7  0x081a2787 in execute_pass_list (pass=0x8499cc0) at
../../gcc-4.3.3/gcc/passes.c:1176
#8  0x081a279a in execute_pass_list (pass=0x8497400) at
../../gcc-4.3.3/gcc/passes.c:1177
#9  0x08238369 in tree_rest_of_compilation (fndecl=0xb7c9bb60) at
../../gcc-4.3.3/gcc/tree-optimize.c:404
#10 0x0831b698 in cgraph_expand_function (node=0xb7c37380) at
../../gcc-4.3.3/gcc/cgraphunit.c:1166
#11 0x0831cffd in cgraph_optimize () at ../../gcc-4.3.3/gcc/cgraphunit.c:1229
#12 0x08057947 in c_write_global_declarations () at
../../gcc-4.3.3/gcc/c-decl.c:8086
#13 0x082041d7 in toplev_main (argc=11, argv=0xbfabc324) at
../../gcc-4.3.3/gcc/toplev.c:1055
#14 0x080a4792 in main (argc=Cannot access memory at address 0x5
) at ../../gcc-4.3.3/gcc/main.c:35

Obviously, my method to implement cbranchsi4 is wrong. Please, I need
advice to have it well done.

Regards,
Florent.


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux