Skip to content

Commit

Permalink
Fix math.min()/math.max() inconsistencies.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Pall committed May 22, 2020
1 parent 1e6e8aa commit 03208c8
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 92 deletions.
6 changes: 3 additions & 3 deletions src/lj_asm_arm.h
Expand Up @@ -1659,8 +1659,8 @@ static void asm_min_max(ASMState *as, IRIns *ir, int cc, int fcc)
asm_intmin_max(as, ir, cc);
}

#define asm_min(as, ir) asm_min_max(as, ir, CC_GT, CC_HI)
#define asm_max(as, ir) asm_min_max(as, ir, CC_LT, CC_LO)
#define asm_min(as, ir) asm_min_max(as, ir, CC_GT, CC_PL)
#define asm_max(as, ir) asm_min_max(as, ir, CC_LT, CC_LE)

/* -- Comparisons --------------------------------------------------------- */

Expand Down Expand Up @@ -1852,7 +1852,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
} else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) {
as->curins--; /* Always skip the loword min/max. */
if (uselo || usehi)
asm_sfpmin_max(as, ir-1, (ir-1)->o == IR_MIN ? CC_HI : CC_LO);
asm_sfpmin_max(as, ir-1, (ir-1)->o == IR_MIN ? CC_PL : CC_LE);
return;
#elif LJ_HASFFI
} else if ((ir-1)->o == IR_CONV) {
Expand Down
6 changes: 3 additions & 3 deletions src/lj_asm_arm64.h
Expand Up @@ -1598,7 +1598,7 @@ static void asm_fpmin_max(ASMState *as, IRIns *ir, A64CC fcc)
Reg dest = (ra_dest(as, ir, RSET_FPR) & 31);
Reg right, left = ra_alloc2(as, ir, RSET_FPR);
right = ((left >> 8) & 31); left &= 31;
emit_dnm(as, A64I_FCSELd | A64F_CC(fcc), dest, left, right);
emit_dnm(as, A64I_FCSELd | A64F_CC(fcc), dest, right, left);
emit_nm(as, A64I_FCMPd, left, right);
}

Expand All @@ -1610,8 +1610,8 @@ static void asm_min_max(ASMState *as, IRIns *ir, A64CC cc, A64CC fcc)
asm_intmin_max(as, ir, cc);
}

#define asm_max(as, ir) asm_min_max(as, ir, CC_GT, CC_HI)
#define asm_min(as, ir) asm_min_max(as, ir, CC_LT, CC_LO)
#define asm_min(as, ir) asm_min_max(as, ir, CC_LT, CC_PL)
#define asm_max(as, ir) asm_min_max(as, ir, CC_GT, CC_LE)

/* -- Comparisons --------------------------------------------------------- */

Expand Down
6 changes: 3 additions & 3 deletions src/lj_asm_mips.h
Expand Up @@ -2121,12 +2121,12 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
right = (left >> 8); left &= 255;
#if !LJ_TARGET_MIPSR6
if (dest == left) {
emit_fg(as, MIPSI_MOVT_D, dest, right);
emit_fg(as, MIPSI_MOVF_D, dest, right);
} else {
emit_fg(as, MIPSI_MOVF_D, dest, left);
emit_fg(as, MIPSI_MOVT_D, dest, left);
if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right);
}
emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : left);
emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? right : left, ismax ? left : right);
#else
emit_fgh(as, ismax ? MIPSI_MAX_D : MIPSI_MIN_D, dest, left, right);
#endif
Expand Down
5 changes: 2 additions & 3 deletions src/lj_asm_ppc.h
Expand Up @@ -1724,9 +1724,8 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
if (tmp == left || tmp == right)
tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_FPR,
dest), left), right));
emit_facb(as, PPCI_FSEL, dest, tmp,
ismax ? left : right, ismax ? right : left);
emit_fab(as, PPCI_FSUB, tmp, left, right);
emit_facb(as, PPCI_FSEL, dest, tmp, left, right);
emit_fab(as, PPCI_FSUB, tmp, ismax ? left : right, ismax ? right : left);
} else {
Reg dest = ra_dest(as, ir, RSET_GPR);
Reg tmp1 = RID_TMP, tmp2 = dest;
Expand Down
53 changes: 19 additions & 34 deletions src/lj_opt_fold.c
Expand Up @@ -1774,8 +1774,6 @@ LJFOLDF(reassoc_intarith_k64)
#endif
}

LJFOLD(MIN MIN any)
LJFOLD(MAX MAX any)
LJFOLD(BAND BAND any)
LJFOLD(BOR BOR any)
LJFOLDF(reassoc_dup)
Expand All @@ -1785,6 +1783,15 @@ LJFOLDF(reassoc_dup)
return NEXTFOLD;
}

LJFOLD(MIN MIN any)
LJFOLD(MAX MAX any)
LJFOLDF(reassoc_dup_minmax)
{
if (fins->op2 == fleft->op2)
return LEFTFOLD; /* (a o b) o b ==> a o b */
return NEXTFOLD;
}

LJFOLD(BXOR BXOR any)
LJFOLDF(reassoc_bxor)
{
Expand Down Expand Up @@ -1823,23 +1830,12 @@ LJFOLDF(reassoc_shift)
return NEXTFOLD;
}

LJFOLD(MIN MIN KNUM)
LJFOLD(MAX MAX KNUM)
LJFOLD(MIN MIN KINT)
LJFOLD(MAX MAX KINT)
LJFOLDF(reassoc_minmax_k)
{
IRIns *irk = IR(fleft->op2);
if (irk->o == IR_KNUM) {
lua_Number a = ir_knum(irk)->n;
lua_Number y = lj_vm_foldarith(a, knumright, fins->o - IR_ADD);
if (a == y) /* (x o k1) o k2 ==> x o k1, if (k1 o k2) == k1. */
return LEFTFOLD;
PHIBARRIER(fleft);
fins->op1 = fleft->op1;
fins->op2 = (IRRef1)lj_ir_knum(J, y);
return RETRYFOLD; /* (x o k1) o k2 ==> x o (k1 o k2) */
} else if (irk->o == IR_KINT) {
if (irk->o == IR_KINT) {
int32_t a = irk->i;
int32_t y = kfold_intop(a, fright->i, fins->o);
if (a == y) /* (x o k1) o k2 ==> x o k1, if (k1 o k2) == k1. */
Expand All @@ -1852,24 +1848,6 @@ LJFOLDF(reassoc_minmax_k)
return NEXTFOLD;
}

LJFOLD(MIN MAX any)
LJFOLD(MAX MIN any)
LJFOLDF(reassoc_minmax_left)
{
if (fins->op2 == fleft->op1 || fins->op2 == fleft->op2)
return RIGHTFOLD; /* (b o1 a) o2 b ==> b; (a o1 b) o2 b ==> b */
return NEXTFOLD;
}

LJFOLD(MIN any MAX)
LJFOLD(MAX any MIN)
LJFOLDF(reassoc_minmax_right)
{
if (fins->op1 == fright->op1 || fins->op1 == fright->op2)
return LEFTFOLD; /* a o2 (a o1 b) ==> a; a o2 (b o1 a) ==> a */
return NEXTFOLD;
}

/* -- Array bounds check elimination -------------------------------------- */

/* Eliminate ABC across PHIs to handle t[i-1] forwarding case.
Expand Down Expand Up @@ -1995,15 +1973,22 @@ LJFOLDF(comm_comp)

LJFOLD(BAND any any)
LJFOLD(BOR any any)
LJFOLD(MIN any any)
LJFOLD(MAX any any)
LJFOLDF(comm_dup)
{
if (fins->op1 == fins->op2) /* x o x ==> x */
return LEFTFOLD;
return fold_comm_swap(J);
}

LJFOLD(MIN any any)
LJFOLD(MAX any any)
LJFOLDF(comm_dup_minmax)
{
if (fins->op1 == fins->op2) /* x o x ==> x */
return LEFTFOLD;
return NEXTFOLD;
}

LJFOLD(BXOR any any)
LJFOLDF(comm_bxor)
{
Expand Down
4 changes: 2 additions & 2 deletions src/lj_vmmath.c
Expand Up @@ -50,8 +50,8 @@ double lj_vm_foldarith(double x, double y, int op)
#if LJ_HASJIT
case IR_ATAN2 - IR_ADD: return atan2(x, y); break;
case IR_LDEXP - IR_ADD: return ldexp(x, (int)y); break;
case IR_MIN - IR_ADD: return x > y ? y : x; break;
case IR_MAX - IR_ADD: return x < y ? y : x; break;
case IR_MIN - IR_ADD: return x < y ? x : y; break;
case IR_MAX - IR_ADD: return x > y ? x : y; break;
#endif
default: return x;
}
Expand Down
4 changes: 2 additions & 2 deletions src/vm_arm.dasc
Expand Up @@ -1716,8 +1716,8 @@ static void build_subroutines(BuildCtx *ctx)
|.endif
|.endmacro
|
| math_minmax math_min, gt, hi
| math_minmax math_max, lt, lo
| math_minmax math_min, gt, pl
| math_minmax math_max, lt, le
|
|//-- String library -----------------------------------------------------
|
Expand Down
4 changes: 2 additions & 2 deletions src/vm_arm64.dasc
Expand Up @@ -1489,8 +1489,8 @@ static void build_subroutines(BuildCtx *ctx)
| b <6
|.endmacro
|
| math_minmax math_min, gt, hi
| math_minmax math_max, lt, lo
| math_minmax math_min, gt, pl
| math_minmax math_max, lt, le
|
|//-- String library -----------------------------------------------------
|
Expand Down
69 changes: 57 additions & 12 deletions src/vm_mips.dasc
Expand Up @@ -1768,7 +1768,7 @@ static void build_subroutines(BuildCtx *ctx)
| b ->fff_res
|. li RD, (2+1)*8
|
|.macro math_minmax, name, intins, fpins
|.macro math_minmax, name, intins, ismax
| .ffunc_1 name
| addu TMP3, BASE, NARGS8:RC
| bne SFARG1HI, TISNUM, >5
Expand Down Expand Up @@ -1822,13 +1822,21 @@ static void build_subroutines(BuildCtx *ctx)
|.endif
|7:
|.if FPU
|.if ismax
| c.olt.d FARG1, FRET1
|.else
| c.olt.d FRET1, FARG1
| fpins FRET1, FARG1
|.endif
| movf.d FRET1, FARG1
|.else
|.if ismax
| bal ->vm_sfcmpogt
|.else
| bal ->vm_sfcmpolt
|.endif
|. nop
| intins SFARG1LO, SFARG2LO, CRET1
| intins SFARG1HI, SFARG2HI, CRET1
| movz SFARG1LO, SFARG2LO, CRET1
| movz SFARG1HI, SFARG2HI, CRET1
|.endif
| b <6
|. addiu TMP2, TMP2, 8
Expand All @@ -1849,8 +1857,8 @@ static void build_subroutines(BuildCtx *ctx)
|
|.endmacro
|
| math_minmax math_min, movz, movf.d
| math_minmax math_max, movn, movt.d
| math_minmax math_min, movz, 0
| math_minmax math_max, movn, 1
|
|//-- String library -----------------------------------------------------
|
Expand Down Expand Up @@ -2692,6 +2700,43 @@ static void build_subroutines(BuildCtx *ctx)
|. move CRET1, CRET2
|.endif
|
|->vm_sfcmpogt:
|.if not FPU
| sll AT, SFARG2HI, 1
| sll TMP0, SFARG1HI, 1
| or CRET1, SFARG2LO, SFARG1LO
| or TMP1, AT, TMP0
| or TMP1, TMP1, CRET1
| beqz TMP1, >8 // Both args +-0: return 0.
|. sltu CRET1, r0, SFARG2LO
| lui TMP1, 0xffe0
| addu AT, AT, CRET1
| sltu CRET1, r0, SFARG1LO
| sltu AT, TMP1, AT
| addu TMP0, TMP0, CRET1
| sltu TMP0, TMP1, TMP0
| or TMP1, AT, TMP0
| bnez TMP1, >9 // Either arg is NaN: return 0 or 1;
|. and AT, SFARG2HI, SFARG1HI
| bltz AT, >5 // Both args negative?
|. nop
| beq SFARG2HI, SFARG1HI, >8
|. sltu CRET1, SFARG2LO, SFARG1LO
| jr ra
|. slt CRET1, SFARG2HI, SFARG1HI
|5: // Swap conditions if both operands are negative.
| beq SFARG2HI, SFARG1HI, >8
|. sltu CRET1, SFARG1LO, SFARG2LO
| jr ra
|. slt CRET1, SFARG1HI, SFARG2HI
|8:
| jr ra
|. nop
|9:
| jr ra
|. li CRET1, 0
|.endif
|
|// Soft-float comparison. Equivalent to c.ole.d a, b or c.ole.d b, a.
|// Input: SFARG*, TMP3. Output: CRET1. Temporaries: AT, TMP0, TMP1.
|->vm_sfcmpolex:
Expand Down Expand Up @@ -2734,24 +2779,24 @@ static void build_subroutines(BuildCtx *ctx)
|. li CRET1, 0
|.endif
|
|.macro sfmin_max, name, intins
|.macro sfmin_max, name, fpcall
|->vm_sf .. name:
|.if JIT and not FPU
| move TMP2, ra
| bal ->vm_sfcmpolt
| bal ->fpcall
|. nop
| move TMP0, CRET1
| move SFRETHI, SFARG1HI
| move SFRETLO, SFARG1LO
| move ra, TMP2
| intins SFRETHI, SFARG2HI, TMP0
| movz SFRETHI, SFARG2HI, TMP0
| jr ra
|. intins SFRETLO, SFARG2LO, TMP0
|. movz SFRETLO, SFARG2LO, TMP0
|.endif
|.endmacro
|
| sfmin_max min, movz
| sfmin_max max, movn
| sfmin_max min, vm_sfcmpolt
| sfmin_max max, vm_sfcmpogt
|
|//-----------------------------------------------------------------------
|//-- Miscellaneous functions --------------------------------------------
Expand Down

0 comments on commit 03208c8

Please sign in to comment.