This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
cbranchsi4
- From: Florent Defay <spira dot inhabitant at gmail dot com>
- To: gcc-help at gcc dot gnu dot org
- Date: Fri, 10 Jul 2009 09:59:50 +0200
- Subject: cbranchsi4
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.