tcg/optimize: Sink commutative operand swapping into fold functions
Most of these are handled by creating a fold_const2_commutative to handle all of the binary operators. The rest were already handled on a case-by-case basis in the switch, and have their own fold function in which to place the call. We now have only one major switch on TCGOpcode. Introduce NO_DEST and a block comment for swap_commutative in order to make the handling of brcond and movcond opcodes cleaner. Reviewed-by: Luis Pires <luis.pires@eldorado.org.br> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
		
							parent
							
								
									9531c078ff
								
							
						
					
					
						commit
						7a2f708452
					
				
							
								
								
									
										142
									
								
								tcg/optimize.c
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								tcg/optimize.c
									
									
									
									
									
								
							| @ -577,6 +577,19 @@ static int do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c) | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * swap_commutative: | ||||
|  * @dest: TCGArg of the destination argument, or NO_DEST. | ||||
|  * @p1: first paired argument | ||||
|  * @p2: second paired argument | ||||
|  * | ||||
|  * If *@p1 is a constant and *@p2 is not, swap. | ||||
|  * If *@p2 matches @dest, swap. | ||||
|  * Return true if a swap was performed. | ||||
|  */ | ||||
| 
 | ||||
| #define NO_DEST  temp_arg(NULL) | ||||
| 
 | ||||
| static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2) | ||||
| { | ||||
|     TCGArg a1 = *p1, a2 = *p2; | ||||
| @ -696,6 +709,12 @@ static bool fold_const2(OptContext *ctx, TCGOp *op) | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| static bool fold_const2_commutative(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     swap_commutative(op->args[0], &op->args[1], &op->args[2]); | ||||
|     return fold_const2(ctx, op); | ||||
| } | ||||
| 
 | ||||
| static bool fold_masks(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     uint64_t a_mask = ctx->a_mask; | ||||
| @ -832,7 +851,7 @@ static bool fold_xx_to_x(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_add(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xi_to_x(ctx, op, 0)) { | ||||
|         return true; | ||||
|     } | ||||
| @ -891,6 +910,10 @@ static bool fold_addsub2(OptContext *ctx, TCGOp *op, bool add) | ||||
| 
 | ||||
| static bool fold_add2(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     /* Note that the high and low parts may be independently swapped. */ | ||||
|     swap_commutative(op->args[0], &op->args[2], &op->args[4]); | ||||
|     swap_commutative(op->args[1], &op->args[3], &op->args[5]); | ||||
| 
 | ||||
|     return fold_addsub2(ctx, op, true); | ||||
| } | ||||
| 
 | ||||
| @ -898,7 +921,7 @@ static bool fold_and(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     uint64_t z1, z2; | ||||
| 
 | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xi_to_i(ctx, op, 0) || | ||||
|         fold_xi_to_x(ctx, op, -1) || | ||||
|         fold_xx_to_x(ctx, op)) { | ||||
| @ -950,8 +973,13 @@ static bool fold_andc(OptContext *ctx, TCGOp *op) | ||||
| static bool fold_brcond(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     TCGCond cond = op->args[2]; | ||||
|     int i = do_constant_folding_cond(ctx->type, op->args[0], op->args[1], cond); | ||||
|     int i; | ||||
| 
 | ||||
|     if (swap_commutative(NO_DEST, &op->args[0], &op->args[1])) { | ||||
|         op->args[2] = cond = tcg_swap_cond(cond); | ||||
|     } | ||||
| 
 | ||||
|     i = do_constant_folding_cond(ctx->type, op->args[0], op->args[1], cond); | ||||
|     if (i == 0) { | ||||
|         tcg_op_remove(ctx->tcg, op); | ||||
|         return true; | ||||
| @ -966,10 +994,14 @@ static bool fold_brcond(OptContext *ctx, TCGOp *op) | ||||
| static bool fold_brcond2(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     TCGCond cond = op->args[4]; | ||||
|     int i = do_constant_folding_cond2(&op->args[0], &op->args[2], cond); | ||||
|     TCGArg label = op->args[5]; | ||||
|     int inv = 0; | ||||
|     int i, inv = 0; | ||||
| 
 | ||||
|     if (swap_commutative2(&op->args[0], &op->args[2])) { | ||||
|         op->args[4] = cond = tcg_swap_cond(cond); | ||||
|     } | ||||
| 
 | ||||
|     i = do_constant_folding_cond2(&op->args[0], &op->args[2], cond); | ||||
|     if (i >= 0) { | ||||
|         goto do_brcond_const; | ||||
|     } | ||||
| @ -1219,7 +1251,7 @@ static bool fold_dup2(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_eqv(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xi_to_x(ctx, op, -1) || | ||||
|         fold_xi_to_not(ctx, op, 0)) { | ||||
|         return true; | ||||
| @ -1381,8 +1413,20 @@ static bool fold_mov(OptContext *ctx, TCGOp *op) | ||||
| static bool fold_movcond(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     TCGCond cond = op->args[5]; | ||||
|     int i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond); | ||||
|     int i; | ||||
| 
 | ||||
|     if (swap_commutative(NO_DEST, &op->args[1], &op->args[2])) { | ||||
|         op->args[5] = cond = tcg_swap_cond(cond); | ||||
|     } | ||||
|     /*
 | ||||
|      * Canonicalize the "false" input reg to match the destination reg so | ||||
|      * that the tcg backend can implement a "move if true" operation. | ||||
|      */ | ||||
|     if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) { | ||||
|         op->args[5] = cond = tcg_invert_cond(cond); | ||||
|     } | ||||
| 
 | ||||
|     i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond); | ||||
|     if (i >= 0) { | ||||
|         return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[4 - i]); | ||||
|     } | ||||
| @ -1428,7 +1472,7 @@ static bool fold_mul(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_mul_highpart(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xi_to_i(ctx, op, 0)) { | ||||
|         return true; | ||||
|     } | ||||
| @ -1437,6 +1481,8 @@ static bool fold_mul_highpart(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_multiply2(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     swap_commutative(op->args[0], &op->args[2], &op->args[3]); | ||||
| 
 | ||||
|     if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])) { | ||||
|         uint64_t a = arg_info(op->args[2])->val; | ||||
|         uint64_t b = arg_info(op->args[3])->val; | ||||
| @ -1480,7 +1526,7 @@ static bool fold_multiply2(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_nand(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xi_to_not(ctx, op, -1)) { | ||||
|         return true; | ||||
|     } | ||||
| @ -1509,7 +1555,7 @@ static bool fold_neg(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_nor(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xi_to_not(ctx, op, 0)) { | ||||
|         return true; | ||||
|     } | ||||
| @ -1529,7 +1575,7 @@ static bool fold_not(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_or(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xi_to_x(ctx, op, 0) || | ||||
|         fold_xx_to_x(ctx, op)) { | ||||
|         return true; | ||||
| @ -1581,8 +1627,13 @@ static bool fold_remainder(OptContext *ctx, TCGOp *op) | ||||
| static bool fold_setcond(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     TCGCond cond = op->args[3]; | ||||
|     int i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond); | ||||
|     int i; | ||||
| 
 | ||||
|     if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) { | ||||
|         op->args[3] = cond = tcg_swap_cond(cond); | ||||
|     } | ||||
| 
 | ||||
|     i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond); | ||||
|     if (i >= 0) { | ||||
|         return tcg_opt_gen_movi(ctx, op, op->args[0], i); | ||||
|     } | ||||
| @ -1594,9 +1645,13 @@ static bool fold_setcond(OptContext *ctx, TCGOp *op) | ||||
| static bool fold_setcond2(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     TCGCond cond = op->args[5]; | ||||
|     int i = do_constant_folding_cond2(&op->args[1], &op->args[3], cond); | ||||
|     int inv = 0; | ||||
|     int i, inv = 0; | ||||
| 
 | ||||
|     if (swap_commutative2(&op->args[1], &op->args[3])) { | ||||
|         op->args[5] = cond = tcg_swap_cond(cond); | ||||
|     } | ||||
| 
 | ||||
|     i = do_constant_folding_cond2(&op->args[1], &op->args[3], cond); | ||||
|     if (i >= 0) { | ||||
|         goto do_setcond_const; | ||||
|     } | ||||
| @ -1774,7 +1829,7 @@ static bool fold_tcg_ld(OptContext *ctx, TCGOp *op) | ||||
| 
 | ||||
| static bool fold_xor(OptContext *ctx, TCGOp *op) | ||||
| { | ||||
|     if (fold_const2(ctx, op) || | ||||
|     if (fold_const2_commutative(ctx, op) || | ||||
|         fold_xx_to_i(ctx, op, 0) || | ||||
|         fold_xi_to_x(ctx, op, 0) || | ||||
|         fold_xi_to_not(ctx, op, -1)) { | ||||
| @ -1827,63 +1882,6 @@ void tcg_optimize(TCGContext *s) | ||||
|             ctx.type = TCG_TYPE_I32; | ||||
|         } | ||||
| 
 | ||||
|         /* For commutative operations make constant second argument */ | ||||
|         switch (opc) { | ||||
|         CASE_OP_32_64_VEC(add): | ||||
|         CASE_OP_32_64_VEC(mul): | ||||
|         CASE_OP_32_64_VEC(and): | ||||
|         CASE_OP_32_64_VEC(or): | ||||
|         CASE_OP_32_64_VEC(xor): | ||||
|         CASE_OP_32_64(eqv): | ||||
|         CASE_OP_32_64(nand): | ||||
|         CASE_OP_32_64(nor): | ||||
|         CASE_OP_32_64(muluh): | ||||
|         CASE_OP_32_64(mulsh): | ||||
|             swap_commutative(op->args[0], &op->args[1], &op->args[2]); | ||||
|             break; | ||||
|         CASE_OP_32_64(brcond): | ||||
|             if (swap_commutative(-1, &op->args[0], &op->args[1])) { | ||||
|                 op->args[2] = tcg_swap_cond(op->args[2]); | ||||
|             } | ||||
|             break; | ||||
|         CASE_OP_32_64(setcond): | ||||
|             if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) { | ||||
|                 op->args[3] = tcg_swap_cond(op->args[3]); | ||||
|             } | ||||
|             break; | ||||
|         CASE_OP_32_64(movcond): | ||||
|             if (swap_commutative(-1, &op->args[1], &op->args[2])) { | ||||
|                 op->args[5] = tcg_swap_cond(op->args[5]); | ||||
|             } | ||||
|             /* For movcond, we canonicalize the "false" input reg to match
 | ||||
|                the destination reg so that the tcg backend can implement | ||||
|                a "move if true" operation.  */ | ||||
|             if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) { | ||||
|                 op->args[5] = tcg_invert_cond(op->args[5]); | ||||
|             } | ||||
|             break; | ||||
|         CASE_OP_32_64(add2): | ||||
|             swap_commutative(op->args[0], &op->args[2], &op->args[4]); | ||||
|             swap_commutative(op->args[1], &op->args[3], &op->args[5]); | ||||
|             break; | ||||
|         CASE_OP_32_64(mulu2): | ||||
|         CASE_OP_32_64(muls2): | ||||
|             swap_commutative(op->args[0], &op->args[2], &op->args[3]); | ||||
|             break; | ||||
|         case INDEX_op_brcond2_i32: | ||||
|             if (swap_commutative2(&op->args[0], &op->args[2])) { | ||||
|                 op->args[4] = tcg_swap_cond(op->args[4]); | ||||
|             } | ||||
|             break; | ||||
|         case INDEX_op_setcond2_i32: | ||||
|             if (swap_commutative2(&op->args[1], &op->args[3])) { | ||||
|                 op->args[5] = tcg_swap_cond(op->args[5]); | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         /* Assume all bits affected, and no bits known zero. */ | ||||
|         ctx.a_mask = -1; | ||||
|         ctx.z_mask = -1; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Richard Henderson
						Richard Henderson