mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	YJIT: eliminate redundant mov in csel/cmov on x86 (#6348)
* Eliminate redundant mov in csel/cmov. Translate mov reg,0 into xor * Fix x86 asm test * Remove dbg!() * xor optimization unsound because it resets flags
This commit is contained in:
		
							parent
							
								
									2a08a39d7d
								
							
						
					
					
						commit
						5b5c627d37
					
				
				
				Notes:
				
					git
				
				2022-09-10 07:41:48 +09:00 
				
			
			Merged-By: maximecb <maximecb@ruby-lang.org>
					 1 changed files with 31 additions and 24 deletions
				
			
		|  | @ -145,7 +145,7 @@ impl Assembler | |||
|                     if !value.special_const_p() || imm_num_bits(value.as_i64()) > 32 { | ||||
|                         asm.load(iterator.map_opnd(*opnd)) | ||||
|                     } else { | ||||
|                         iterator.map_opnd(*opnd) | ||||
|                         Opnd::UImm(value.as_u64()) | ||||
|                     } | ||||
|                 } else { | ||||
|                     iterator.map_opnd(*opnd) | ||||
|  | @ -221,18 +221,25 @@ impl Assembler | |||
|                 Insn::CSelLE { truthy, falsy, out } | | ||||
|                 Insn::CSelG { truthy, falsy, out } | | ||||
|                 Insn::CSelGE { truthy, falsy, out } => { | ||||
|                     match truthy { | ||||
|                         Opnd::Reg(_) | Opnd::InsnOut { .. } => {}, | ||||
|                         _ => { | ||||
|                     match unmapped_opnds[0] { | ||||
|                         // If we have an instruction output whose live range
 | ||||
|                         // spans beyond this instruction, we have to load it.
 | ||||
|                         Opnd::InsnOut { idx, .. } => { | ||||
|                             if live_ranges[idx] > index { | ||||
|                                 *truthy = asm.load(*truthy); | ||||
|                             } | ||||
|                         }, | ||||
|                         Opnd::UImm(_) | Opnd::Imm(_) | Opnd::Value(_) => { | ||||
|                             *truthy = asm.load(*truthy); | ||||
|                         }, | ||||
|                         _ => {} | ||||
|                     }; | ||||
| 
 | ||||
|                     match falsy { | ||||
|                         Opnd::Reg(_) | Opnd::InsnOut { .. } => {}, | ||||
|                         _ => { | ||||
|                         Opnd::UImm(_) | Opnd::Imm(_) => { | ||||
|                             *falsy = asm.load(*falsy); | ||||
|                         } | ||||
|                         }, | ||||
|                         _ => {} | ||||
|                     }; | ||||
| 
 | ||||
|                     *out = asm.next_opnd_out(Opnd::match_num_bits(&[*truthy, *falsy])); | ||||
|  | @ -350,6 +357,14 @@ impl Assembler | |||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         fn emit_csel(cb: &mut CodeBlock, truthy: Opnd, falsy: Opnd, out: Opnd, cmov_fn: fn(&mut CodeBlock, X86Opnd, X86Opnd)) { | ||||
|             if out != truthy { | ||||
|                 mov(cb, out.into(), truthy.into()); | ||||
|             } | ||||
|             cmov_fn(cb, out.into(), falsy.into()); | ||||
|         } | ||||
| 
 | ||||
|         //dbg!(&self.insns);
 | ||||
| 
 | ||||
|         // List of GC offsets
 | ||||
|  | @ -609,36 +624,28 @@ impl Assembler | |||
|                 Insn::Breakpoint => int3(cb), | ||||
| 
 | ||||
|                 Insn::CSelZ { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmovnz(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmovnz); | ||||
|                 }, | ||||
|                 Insn::CSelNZ { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmovz(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmovz); | ||||
|                 }, | ||||
|                 Insn::CSelE { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmovne(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmovne); | ||||
|                 }, | ||||
|                 Insn::CSelNE { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmove(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmove); | ||||
|                 }, | ||||
|                 Insn::CSelL { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmovge(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmovge); | ||||
|                 }, | ||||
|                 Insn::CSelLE { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmovg(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmovg); | ||||
|                 }, | ||||
|                 Insn::CSelG { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmovle(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmovle); | ||||
|                 }, | ||||
|                 Insn::CSelGE { truthy, falsy, out } => { | ||||
|                     mov(cb, out.into(), truthy.into()); | ||||
|                     cmovl(cb, out.into(), falsy.into()); | ||||
|                     emit_csel(cb, *truthy, *falsy, *out, cmovl); | ||||
|                 } | ||||
|                 Insn::LiveReg { .. } => (), // just a reg alloc signal, no code
 | ||||
|                 Insn::PadEntryExit => { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Maxime Chevalier-Boisvert
						Maxime Chevalier-Boisvert