This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: how can I split 1 mov insn into 2 sub_mov and 1 combine?
On Thu, Mar 17, 2011 at 2:11 PM, WANG.Jiong <wong.kwongyuan@gmail.com> wrote:
> define_split should be the correct way to handle this.
> You should first use define_split to break your 256bit pattern and generate
> legitimized 128bit rtl pattern sequence ?for you processor
> mips_output_move should only be used to handle those legitimized one.
>
> ?256 bit rtl pattern ?----> define_split
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?V
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rtl pattern 1 ? ? ?--->
> mips_output_move () -> ?corresponding instruciton
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rtl pattern 2 ? ? ...
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rtl pattern 3 ? ? ...
>
> And I am doubt abour you pattern
>
> (insn 31 30 32 3 hr-simd.c:28 (set (mem/c/i:V4DI (reg/f:DI 253
> virtual-stack-vars) [0 s+0 S32 A256])
> ? ? ? ?(reg:V4DI 257 [ D.5235 ])) -1 (nil))
>
>
> You set the memeory from a register?
>
>
>
> On 03/17/2011 12:59 PM, Liu wrote:
>>
>> hi all
>> Our processor have a outrageous load insn, so I have to make gcc
>> support it. But when I tried some way, I failed.
>> When we suppose a load should be:
>> load_256 ? ? ?$z1, 16($fp) ? ? ? ? ?;load 256bits to a 256bits-wide
>> register.
>> we have to split it into:
>> load_low_128 ? ? ?$z1, 16($fp) ? ? ? ? ?;load 128bits to the low
>> 128bits of a 256bits-wide register.
>> load_low_128 ? ? ?$z2, 32($fp) ? ? ? ? ?;load 128bits to the low
>> 128bits of a 256bits-wide register.
>> combine_2_to_1 ? ? ?$z1, $z1, $z2, 0x20 ? ? ? ? ?;combine them together.
>>
>> in mips_output_move, I can return a string such like "load_256 ? ? ?%0,
>> %1",
>> but I can't return "load_low_128 ? ? ?%0, %1\n
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?load_low_128 ? ? ?%2, %3\n
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?combine_2_to_1 ? ? ?%0, %0, %2, 0x20"
>> %3 is %1+16bytes offset, %0 and %2 are 256bits-wide registers, 0x20 is a
>> const.
>>
>> in define_insn "mov<mode>_internal", I can't using emit_insn(gen_xxx()).
>>
>> when I using emit_insn(gen_xxx()) in define_expand "mov<mode>" I get a
>> error like:
>> root@localhost:~/# mips64el-unknown-linux-gnu-gcc -S -march=xx xx-simd.c
>> xx-simd.c: In function 'test_vpaddd_u':
>> xx-simd.c:33:1: error: unrecognizable insn:
>> (insn 31 30 32 3 hr-simd.c:28 (set (mem/c/i:V4DI (reg/f:DI 253
>> virtual-stack-vars) [0 s+0 S32 A256])
>> ? ? ? ? (reg:V4DI 257 [ D.5235 ])) -1 (nil))
>> xx-simd.c:33:1: internal compiler error: in extract_insn, at recog.c:2103
>> Please submit a full bug report,
>>
>> Please show me a path, thank you very much!
>>
>> -Liu
>>
>
>
Sorry WANG
another toolchain take me several days.
split 256-bits move like:
(define_split
[(set (match_operand:ZDSOTDWHB 0 "nonimmediate_operand")
(match_operand:ZDSOTDWHB 1 "move_operand"))]
"TARGET_1 && reload_completed"
[(const_int 0)]
{
mips_split_octupleword_move (operands[0], operands[1]);
DONE;
})
mips_split_octupleword_move is:
void
mips_split_octupleword_move (rtx dest, rtx src)
{
rtx addr, tmp_reg, imm8;
enum machine_mode mode;
enum rtx_code dest_code, src_code;
dest_code = GET_CODE (dest);
src_code = GET_CODE (src);
mode = GET_MODE (dest);
if (dest_code == REG && ZZ_REG_P (REGNO(dest)) && src_code == MEM)
{
mips_emit_move (dest, src);
addr = plus_constant (src, 16);
if (GET_MODE (dest) == V32QImode)
tmp_reg = gen_reg_rtx (V32QImode);
else if (GET_MODE (dest) == V16HImode)
tmp_reg = gen_reg_rtx (V16HImode);
else if (GET_MODE (dest) == V8SImode)
tmp_reg = gen_reg_rtx (V8SImode);
else if (GET_MODE (dest) == V4DImode)
tmp_reg = gen_reg_rtx (V4DImode);
else if (GET_MODE (dest) == V2TImode)
tmp_reg = gen_reg_rtx (V2TImode);
else if (GET_MODE (dest) == OImode)
tmp_reg = gen_reg_rtx (OImode);
else if (GET_MODE (dest) == V8SFmode)
tmp_reg = gen_reg_rtx (V8SFmode);
else if (GET_MODE (dest) == V4DFmode)
tmp_reg = gen_reg_rtx (V4DFmode);
else
printf("Can't alloc Pseudo-Register for vload. \n");
mips_emit_move (tmp_reg, addr);
imm8 = GEN_INT(0x20);
emit_insn (gen_vpermutqi (dest, dest, tmp_reg, imm8));
}
else if (src_code == REG && ZZ_REG_P (REGNO(src)) && dest_code ==MEM)
{
mips_emit_move (dest, src);
addr = plus_constant (src, 16);
if (GET_MODE (dest) == V32QImode)
tmp_reg = gen_reg_rtx (V32QImode);
else if (GET_MODE (dest) == V16HImode)
tmp_reg = gen_reg_rtx (V16HImode);
else if (GET_MODE (dest) == V8SImode)
tmp_reg = gen_reg_rtx (V8SImode);
else if (GET_MODE (dest) == V4DImode)
tmp_reg = gen_reg_rtx (V4DImode);
else if (GET_MODE (dest) == V2TImode)
tmp_reg = gen_reg_rtx (V2TImode);
else if (GET_MODE (dest) == OImode)
tmp_reg = gen_reg_rtx (OImode);
else if (GET_MODE (dest) == V8SFmode)
tmp_reg = gen_reg_rtx (V8SFmode);
else if (GET_MODE (dest) == V4DFmode)
tmp_reg = gen_reg_rtx (V4DFmode);
else
printf("Can't alloc Pseudo-Register for vstore. \n");
imm8 = GEN_INT(0x01);
emit_insn (gen_vpextrv2ti (tmp_reg, dest, imm8));
mips_emit_move (tmp_reg, addr);
}
}
then mov<mode>:
(define_expand "mov<mode>"
[(set (match_operand:ZDSOTDWHB 0)
(match_operand:ZDSOTDWHB 1))]
"TARGET_VECTORS"
{
if (mips_legitimize_move (<MODE>mode, operands[0], operands[1]))
DONE;
})
(define_insn "mov<mode>_internal"
[(set (match_operand:ZDSOTDWHB 0 "nonimmediate_operand" "=m,Z,Z")
(match_operand:ZDSOTDWHB 1 "move_operand" "Z,m,Z"))]
"TARGET_VECTORS"
{ return mips_output_move (operands[0], operands[1]); }
[(set_attr "move_type" "vmov")])
mips_output_move has this code:
if (dest_code == REG && ZZ_REG_P (REGNO(dest)))
{
if (src_code == MEM)
{
return "vldql\t%0,%1";
}
}
if (src_code == REG && HR_REG_P (REGNO(src)))
{
if (dest_code == MEM)
{
return "vstql\t%1,%0";
}
}
make and test it, get a error:
root@localhost:~/hr1-toolchain/test# mips64el-unknown-linux-gnu-gcc
-march=zz1 -S vpaddd.c
vpaddd.c: In function 'test_vpaddd_u':
vpaddd.c:33:1: internal compiler error: in gen_reg_rtx, at emit-rtl.c:863
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
emit-rtl.c:863 is gcc_assert (can_create_pseudo_p ());
I have no ideas...