@@ -227,6 +227,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
227227#define  ir_op_flag_d0       ir_op_flag_d
228228#define  ir_op_flag_d1       (ir_op_flag_d | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
229229#define  ir_op_flag_d1X1     (ir_op_flag_d | 1 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
230+ #define  ir_op_flag_d1X2     (ir_op_flag_d | 1 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
230231#define  ir_op_flag_d2       (ir_op_flag_d | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
231232#define  ir_op_flag_d2C      (ir_op_flag_d | IR_OP_FLAG_COMMUTATIVE | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
232233#define  ir_op_flag_d3       (ir_op_flag_d | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
@@ -270,6 +271,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
270271#define  ir_op_flag_s3       (ir_op_flag_s | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
271272#define  ir_op_flag_x1       (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
272273#define  ir_op_flag_x2       (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
274+ #define  ir_op_flag_x2X1     (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 2 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
273275#define  ir_op_flag_x3       (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
274276#define  ir_op_flag_xN       (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | IR_OP_FLAG_VAR_INPUTS)
275277#define  ir_op_flag_a1       (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_ALLOC | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
@@ -392,6 +394,8 @@ void ir_init(ir_ctx *ctx, uint32_t flags, ir_ref consts_limit, ir_ref insns_limi
392394	ctx -> insns_limit  =  insns_limit ;
393395	ctx -> consts_count  =  - (IR_TRUE  -  1 );
394396	ctx -> consts_limit  =  consts_limit ;
397+ 	ctx -> const_hash  =  ctx -> _const_hash ;
398+ 	ctx -> const_hash_mask  =  IR_CONST_HASH_SIZE  -  1 ;
395399	ctx -> fold_cse_limit  =  IR_UNUSED  +  1 ;
396400	ctx -> flags  =  flags ;
397401
@@ -414,6 +418,9 @@ void ir_free(ir_ctx *ctx)
414418{
415419	ir_insn  * buf  =  ctx -> ir_base  -  ctx -> consts_limit ;
416420	ir_mem_free (buf );
421+ 	if  (ctx -> value_params ) {
422+ 		ir_mem_free (ctx -> value_params );
423+ 	}
417424	if  (ctx -> strtab .data ) {
418425		ir_strtab_free (& ctx -> strtab );
419426	}
@@ -468,6 +475,10 @@ void ir_free(ir_ctx *ctx)
468475		ir_list_free ((ir_list * )ctx -> osr_entry_loads );
469476		ir_mem_free (ctx -> osr_entry_loads );
470477	}
478+ 
479+ 	if  (ctx -> const_hash_mask  !=  IR_CONST_HASH_SIZE  -  1 ) {
480+ 		ir_mem_free (ctx -> const_hash );
481+ 	}
471482}
472483
473484ir_ref  ir_unique_const_addr (ir_ctx  * ctx , uintptr_t  addr )
@@ -479,72 +490,64 @@ ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t addr)
479490	insn -> val .u64  =  addr ;
480491	/* don't insert into constants chain */ 
481492	insn -> prev_const  =  IR_UNUSED ;
482- #if  0 
483- 	insn -> prev_const  =  ctx -> prev_const_chain [IR_ADDR ];
484- 	ctx -> prev_const_chain [IR_ADDR ] =  ref ;
485- #endif 
486- #if  0 
487- 	ir_insn  * prev_insn , * next_insn ;
488- 	ir_ref  next ;
489- 
490- 	prev_insn  =  NULL ;
491- 	next  =  ctx -> prev_const_chain [IR_ADDR ];
492- 	while  (next ) {
493- 		next_insn  =  & ctx -> ir_base [next ];
494- 		if  (UNEXPECTED (next_insn -> val .u64  >= addr )) {
495- 			break ;
496- 		}
497- 		prev_insn  =  next_insn ;
498- 		next  =  next_insn -> prev_const ;
499- 	}
500- 
501- 	if  (prev_insn ) {
502- 		insn -> prev_const  =  prev_insn -> prev_const ;
503- 		prev_insn -> prev_const  =  ref ;
504- 	} else  {
505- 		insn -> prev_const  =  ctx -> prev_const_chain [IR_ADDR ];
506- 		ctx -> prev_const_chain [IR_ADDR ] =  ref ;
507- 	}
508- #endif 
509493
510494	return  ref ;
511495}
512496
497+ IR_ALWAYS_INLINE  uintptr_t  ir_const_hash (ir_val  val , uint32_t  optx )
498+ {
499+ 	return  (val .u64  ^ (val .u64  >> 32 ) ^ optx );
500+ }
501+ 
502+ static  IR_NEVER_INLINE  void  ir_const_hash_rehash (ir_ctx  * ctx )
503+ {
504+ 	ir_insn  * insn ;
505+ 	ir_ref  ref ;
506+ 	uintptr_t  hash ;
507+ 
508+ 	if  (ctx -> const_hash_mask  !=  IR_CONST_HASH_SIZE  -  1 ) {
509+ 		ir_mem_free (ctx -> const_hash );
510+ 	}
511+ 	ctx -> const_hash_mask  =  (ctx -> const_hash_mask  +  1 ) *  2  -  1 ;
512+ 	ctx -> const_hash  =  ir_mem_calloc (ctx -> const_hash_mask  +  1 , sizeof (ir_ref ));
513+ 	for  (ref  =  IR_TRUE  -  1 ; ref  >  - ctx -> consts_count ; ref -- ) {
514+ 		insn  =  & ctx -> ir_base [ref ];
515+ 		hash  =  ir_const_hash (insn -> val , insn -> optx ) &  ctx -> const_hash_mask ;
516+ 		insn -> prev_const  =  ctx -> const_hash [hash ];
517+ 		ctx -> const_hash [hash ] =  ref ;
518+ 	}
519+ }
520+ 
513521ir_ref  ir_const_ex (ir_ctx  * ctx , ir_val  val , uint8_t  type , uint32_t  optx )
514522{
515- 	ir_insn  * insn ,  * prev_insn ;
523+ 	ir_insn  * insn ;
516524	ir_ref  ref , prev ;
525+ 	uintptr_t  hash ;
517526
518527	if  (type  ==  IR_BOOL ) {
519528		return  val .u64  ? IR_TRUE  : IR_FALSE ;
520529	} else  if  (type  ==  IR_ADDR  &&  val .u64  ==  0 ) {
521530		return  IR_NULL ;
522531	}
523- 	prev_insn  =  NULL ;
524- 	ref  =  ctx -> prev_const_chain [type ];
532+ 
533+ 	hash  =  ir_const_hash (val , optx ) &  ctx -> const_hash_mask ;
534+ 	ref  =  ctx -> const_hash [hash ];
525535	while  (ref ) {
526536		insn  =  & ctx -> ir_base [ref ];
527- 		if  (UNEXPECTED (insn -> val .u64  >= val .u64 )) {
528- 			if  (insn -> val .u64  ==  val .u64 ) {
529- 				if  (insn -> optx  ==  optx ) {
530- 					return  ref ;
531- 				}
532- 			} else  {
533- 				break ;
534- 			}
537+ 		if  (insn -> val .u64  ==  val .u64  &&  insn -> optx  ==  optx ) {
538+ 			return  ref ;
535539		}
536- 		prev_insn  =  insn ;
537540		ref  =  insn -> prev_const ;
538541	}
539542
540- 	if  (prev_insn ) {
541- 		prev  =  prev_insn -> prev_const ;
542- 		prev_insn -> prev_const  =  - ctx -> consts_count ;
543- 	} else  {
544- 		prev  =  ctx -> prev_const_chain [type ];
545- 		ctx -> prev_const_chain [type ] =  - ctx -> consts_count ;
543+ 	if  ((uintptr_t )ctx -> consts_count  >  ctx -> const_hash_mask ) {
544+ 		ir_const_hash_rehash (ctx );
545+ 		hash  =  ir_const_hash (val , optx ) &  ctx -> const_hash_mask ;
546546	}
547547
548+ 	prev  =  ctx -> const_hash [hash ];
549+ 	ctx -> const_hash [hash ] =  - ctx -> consts_count ;
550+ 
548551	ref  =  ir_next_const (ctx );
549552	insn  =  & ctx -> ir_base [ref ];
550553	insn -> prev_const  =  prev ;
@@ -2092,10 +2095,10 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(ir_ctx *ctx, ir_ref ref, ir_typ
20922095				if  (insn -> type  ==  type ) {
20932096					return  ref ; /* load forwarding (L2L) */ 
20942097				} else  if  (ir_type_size [insn -> type ] ==  ir_type_size [type ]) {
2095- 					return  ir_fold1 ( ctx ,  IR_OPT ( IR_BITCAST ,  type ),  ref ) ; /* load forwarding with bitcast (L2L) */ 
2098+ 					return  ref ; /* load forwarding with bitcast (L2L) */ 
20962099				} else  if  (ir_type_size [insn -> type ] >  ir_type_size [type ]
20972100						&&  IR_IS_TYPE_INT (type ) &&  IR_IS_TYPE_INT (insn -> type )) {
2098- 					return  ir_fold1 ( ctx ,  IR_OPT ( IR_TRUNC ,  type ),  ref ) ; /* partial load forwarding (L2L) */ 
2101+ 					return  ref ; /* partial load forwarding (L2L) */ 
20992102				}
21002103			}
21012104		} else  if  (insn -> op  ==  IR_VSTORE ) {
@@ -2105,10 +2108,10 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(ir_ctx *ctx, ir_ref ref, ir_typ
21052108				if  (type2  ==  type ) {
21062109					return  insn -> op3 ; /* store forwarding (S2L) */ 
21072110				} else  if  (ir_type_size [type2 ] ==  ir_type_size [type ]) {
2108- 					return  ir_fold1 ( ctx ,  IR_OPT ( IR_BITCAST ,  type ),  insn -> op3 ) ; /* store forwarding with bitcast (S2L) */ 
2111+ 					return  insn -> op3 ; /* store forwarding with bitcast (S2L) */ 
21092112				} else  if  (ir_type_size [type2 ] >  ir_type_size [type ]
21102113						&&  IR_IS_TYPE_INT (type ) &&  IR_IS_TYPE_INT (type2 )) {
2111- 					return  ir_fold1 ( ctx ,  IR_OPT ( IR_TRUNC ,  type ),  insn -> op3 ) ; /* partial store forwarding (S2L) */ 
2114+ 					return  insn -> op3 ; /* partial store forwarding (S2L) */ 
21122115				} else  {
21132116					break ;
21142117				}
@@ -3214,6 +3217,13 @@ ir_ref _ir_VA_ARG(ir_ctx *ctx, ir_type type, ir_ref list)
32143217	return  ctx -> control  =  ir_emit2 (ctx , IR_OPT (IR_VA_ARG , type ), ctx -> control , list );
32153218}
32163219
3220+ ir_ref  _ir_VA_ARG_EX (ir_ctx  * ctx , ir_type  type , ir_ref  list , size_t  size )
3221+ {
3222+ 	IR_ASSERT (ctx -> control );
3223+ 	IR_ASSERT (size  <= 0x7fffffff );
3224+ 	return  ctx -> control  =  ir_emit3 (ctx , IR_OPT (IR_VA_ARG , type ), ctx -> control , list , (ir_ref )size );
3225+ }
3226+ 
32173227ir_ref  _ir_BLOCK_BEGIN (ir_ctx  * ctx )
32183228{
32193229	IR_ASSERT (ctx -> control );
0 commit comments