-
Notifications
You must be signed in to change notification settings - Fork 749
Fix a bug if there is multiple return and one of them is in block #1063
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| gen_commit_values(cc->jit_frame, cc->jit_frame->lp, cc->jit_frame->sp); | ||
| clear_values(cc->jit_frame); | ||
|
|
||
| insn = GEN_INSN(JMP, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to make all "return opcodes" jump to the same func block's end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YES, That is the plan. To avoid creating the same function return basic block multiple times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, an issue is that the function return values here are in current block, and haven't been copied to the dest block (block_func).
Seems that we needn't to gen_commit_values, just copy results and clear values:
SET_BB_END_BCIP(cc->cur_basic_block, *p_frame_ip - 1);
copy_block_arities(cc, frame_sp_dst, block_func->result_types,
block_func->result_count);
clear_values(cc->jit_frame);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the following end of the JitBlock will do that job
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The end of JitBlock might not be executed:
(func result i32
block
i32.const 1234
return
i32.const 4567
end
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another issue is about the performance, here it just copies the return values from current block to previous frame and returns to the caller. If jumping to func block, it needs to copy return values to that block, and in its end, copies values again to previous frame, which degrades the performance.
How about not changing it?
| /* start a new basic block */ | ||
| CREATE_BASIC_BLOCK(basic_block); | ||
| SET_BB_BEGIN_BCIP(basic_block, *p_frame_ip); | ||
| SET_BUILDER_POS(basic_block); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to create new basic block, it has no processor, no other code will jump to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the current basic block is closed with a JMP, I think we will need a new basic block to include the next IRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to create the new basic block, the next handle_next_reachable_block() will find a new jit block, create it's end or else basic block if it is not created, and then start to translate that basic block.
|
The patch will prevent (func (export "e0") (param i32) (result i32)
(i32.const 3)
(if (param i32) (result i32) (local.get 0)
(then
(block (param i32) (result i32)
(drop)
(i32.const 7)
(return)
)
)
(else
(return)
)
)
(return)
)Generated IRs and some problems(Not sure if they are problems or not)
|
1e8373f to
e5b9124
Compare
| *p_frame_ip = block->wasm_code_end + 1; | ||
| return handle_op_end(cc, p_frame_ip, false); | ||
| return handle_op_end( | ||
| cc, p_frame_ip, block == jit_block_stack_top(&cc->block_stack)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why adding block == jit_block_stack_top(&cc->block_stack), for case below:
(module
(type $0 (func (result i32)))
(export "test" (func $1))
(func $1 (type $0)
(result i32)
i32.const 5678
(block $l (param i32) (result i32)
i32.const 1234
i32.add
i32.const 1
br 0
drop
i32.const 666
)
)
)Two 'JMP' instructions are generated in L2:
L2:
; PREDS(L0)
; BEGIN_BCIP=0x0027 END_BCIP=0x0038
ADD i7, 0x162e, 0x4d2
ADD I21, I0, 0x90L
STI32 0x1, I21, 0x0
JMP L3
JMP L3
; SUCCS(L3)
| else if (block->incoming_insns_for_end_bb) { | ||
| *p_frame_ip = block->wasm_code_end + 1; | ||
| return handle_op_end(cc, p_frame_ip, false); | ||
| return handle_op_end(cc, p_frame_ip, block == first_block); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why need to add block == first_block? For case below:
(module
(type $0 (func (result i32)))
(export "test" (func $1))
(func $1 (type $0)
(result i32)
i32.const 5678
(block $l (param i32) (result i32)
i32.const 1234
i32.add
i32.const 1
br 0
drop
i32.const 666
)
)
)Dumplicated JMP instruction are generated in L2:
L2:
; PREDS(L0)
; BEGIN_BCIP=0x0027 END_BCIP=0x0038
ADD i7, 0x162e, 0x4d2
ADD I21, I0, 0x90L
STI32 0x1, I21, 0x0
JMP L3
JMP L3
; SUCCS(L3)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try to handle one of the above problems. (else return end)
(func (export "e0") (param i32) (result i32)
(i32.const 3)
(if (param i32) (result i32) (local.get 0)
(then
(block (param i32) (result i32)
(drop)
(i32.const 7)
(return)
)
)
(else
(return)
)
)
(return)
)
And missing jmp in ELSE branch
L4:
; PREDS(L2)
; BEGIN_BCIP=0x002f END_BCIP=0x0030
LDI32 i9, I0, 0x94 ;-> i32.const 3
LDI64 I23, I0, 0x0 ;-> function return
LDI64 I24, I23, 0x70
STI32 i9, I24, 0x0
ADD I24, I24, 0x4L
STI64 I24, I23, 0x70
STI64 I0, I15, 0xc90
STI64 I23, I15, 0x68
MOV I0, I23
RETURNBC 0x0, VOID, VOID
STI32 i9, I0, 0x94 ;-> gen_commit_value()
;-> miss a JMP ?
; SUCCS()
Guess we need more condition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to jmp here,RETURNBC will return to caller, the following insns won't be executed. In fact, the STI32 should not be generated. Guess there are unneeded commit_values called.
b562b2b to
e826e2d
Compare
here is a case:
``` wast
(func (export "e0") (result i32)
(block
(i32.const 3)
(return)
)
(i32.const 7)
(return)
)
```
| { | ||
| JitBlock *block = cc->block_stack.block_list_end, *block_prev; | ||
| JitBlock *block = jit_block_stack_top(&cc->block_stack); | ||
| JitBlock *first_block = jit_block_stack_top(&cc->block_stack); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused line, had better remove it
| /* IF...ELSE... and return from ELSE */ | ||
| else { | ||
| *p_frame_ip = block->wasm_code_end + 1; | ||
| return handle_op_end(cc, p_frame_ip, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure whether this code causes the issue, for case below:
(module
(func (export "test") (param i32) (result i32)
(i32.const 3)
(if (param i32) (result i32) (local.get 0)
(then
(block (param i32) (result i32)
(drop)
(i32.const 7)
(return)
)
)
(else
(return)
)
)
(return)
)
)Unnecessary INSNs are generated after RETURNBC:
L3:
; PREDS(L2)
; BEGIN_BCIP=0x0029 END_BCIP=0x0030
LDI32 i8, I0, 0x94
LDI64 I21, I0, 0x0
LDI64 I22, I21, 0x70
STI32 0x7, I22, 0x0
ADD I22, I22, 0x4L
STI64 I22, I21, 0x70
STI64 I0, I15, 0xc90
STI64 I21, I15, 0x68
MOV I0, I21
RETURNBC 0x0, VOID, VOID
STI32 0x7, I0, 0x94 ====> Unused INSN
JMP L5 ====> Unused INSN
; SUCCS(L5)
L4:
; PREDS(L2)
; BEGIN_BCIP=0x0031 END_BCIP=0x0032
LDI32 i9, I0, 0x94
LDI64 I23, I0, 0x0
LDI64 I24, I23, 0x70
STI32 i9, I24, 0x0
ADD I24, I24, 0x4L
STI64 I24, I23, 0x70
STI64 I0, I15, 0xc90
STI64 I23, I15, 0x68
MOV I0, I23
RETURNBC 0x0, VOID, VOID
STI32 i9, I0, 0x94 ====> Unused INSN
JMP L5 ====> Unused INSN
; SUCCS(L5)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I noticed that. Seems if if there is a return in a basic block, we should skip the end. But needs to take care cases of branches
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I merged the patch firstly, let's test and fix if issues are found.
| block = jit_block_stack_top(&cc->block_stack); | ||
| } | ||
| } | ||
| /* Branches create a JMP*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For below case:
(module
(type $0 (func (param i32 i32) (result i32)))
(export "test" (func $1))
(func $1 (type $0)
(param $0 i32)
(param $1 i32)
(result i32)
local.get $0
local.get $1
(if (param i32 i32) (result i32) (local.get $0)
(then
(i32.add)
br 1
)
(else
(i32.sub)
local.get $1
br 1
)
)
)
)Duplicated JMP is generated, and unnecessary LD/ST are generated:
L3:
; PREDS(L2)
; BEGIN_BCIP=0x002c END_BCIP=0x002f
LDI32 i9, I0, 0x98
LDI32 i10, I0, 0x9c
ADD i11, i9, i10
JMP L6
JMP L5 ====> Unnecessary JMP
; SUCCS(L5)
L4:
; PREDS(L2)
; BEGIN_BCIP=0x0030 END_BCIP=0x0035
LDI32 i12, I0, 0x98
LDI32 i13, I0, 0x9c
SUB i14, i12, i13
LDI32 i15, I0, 0x94
ADD I21, I0, 0x98L
STI32 i15, I21, 0x0
JMP L6
JMP L5 ====> Unnecessary JMP
L5:
; PREDS(L3 L4)
; BEGIN_BCIP=0x0036 END_BCIP=0x0036
LDI32 i16, I0, 0x98
STI32 i16, I0, 0x98 ==> Unnecessary LDI32 and STDI32
JMP L6
; SUCCS(L6)
It is really not easy to fix the issues, I fix some issues and modify this file directly, some cases are tested successfully. If there are issues found, please help report and let's fix them together.
Fix issues of compiling control related opcodes (bytecodealliance#1063)
No description provided.