sig writes:
I'm currently testing my asm-parser. And found it generates unneeded instruction (mov eax,eax): code of asm method:
message4: arg1 with: arg2 | b c | self pragma: #cdecl. c := arg1 + arg2. b := arg1 / arg2. ^ c + b
produced intermediate by parser: #(#(#block 1 #(#mov #(#add #(#argument #arg1) #(#argument #arg2)) #c) #(#mov #(#div #(#argument #arg1) #(#argument #arg2) 'temp7D6') #b) #(#return #(#add #c #b))))
then with transformed arguments and cdecl prologue/epilogue: #(#(#block 1 #(#push #ebp) #(#mov #esp #ebp)) #(#block 3 #(#mov #(#add #(#mem #(#add #ebp -4)) #(#mem #(#add #ebp -8))) 't1') #(#mov #(#div #(#mem #(#add #ebp -4)) #(#mem #(#add #ebp -8)) 't3') 't2') #(#mov #(#add 't1' 't2') #eax) #(#jmp #block2)) #(#block 2 #(#mov #ebp #esp) #(#pop #ebp) #(#ret)))
and then i using LowLevelOptimiser ->InstructionSelector -> ColouringRegisterAllocator -> JumpRemover :
#(#(#block 1 #(#push #ebp) #(#mov #esp #ebp)) #(#block 3 #(#mov #(-8 #ebp) #ebx) #(#add #(-4 #ebp) #ebx) #(#mov #(-4 #ebp) #eax) #(#mov #(-8 #ebp) #ecx) #(#cdq) #(#div #ecx)
#(#mov #eax #eax)
#(#add #ebx #eax)) #(#block 2 #(#mov #ebp #esp) #(#pop #ebp) #(#ret)))
I suppose fix could be simple by testing in MedMov>>#visitWith: that if reg1 = reg2 then return nil , which will be interpreted as no-op by block.
I'm not sure why Exupery is doing that. The register uses a decent move coalescer which will first try to create moves like (mov eax eax) then remove them. The register allocator goes to some lengths to do this.
It's possible that you've found a case where the no-op move removal code isn't getting used, though I'm not sure where it is. It will be interesting to here if the problem is still there after you change how you're creating intermediate to make sure that there's only one #eax register object. 1)
Exupery relies on object identity inside it's intermediate, this is a design decision that's probabably in many places by now.
Bryce
1) Sig and I've spoken on irc about this.