Skip to content

Commit cc3c51e

Browse files
committed
[sil-optimizer] Don't constant fold eq comparisons b/w inf and non-inf
This commit modifes the constant folder to not handle equality comparisons b/w infinity and non-infinity operands. In such comparisons, special floating point types - Float80 and Float16, may come into play and pattern matching againt them complicates the constant folding logic more than we'd like.
1 parent c800dd7 commit cc3c51e

File tree

2 files changed

+29
-27
lines changed

2 files changed

+29
-27
lines changed

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ static SILValue constantFoldCompareFloat(BuiltinInst *BI, BuiltinValueKind ID) {
612612
}
613613
}
614614

615-
// Everything is less than, less than equal to or unequal to positive infinity
615+
// Everything is less than or less than equal to positive infinity
616616
if (match(BI,
617617
m_CombineOr(
618618
// Inf > x
@@ -627,12 +627,6 @@ static SILValue constantFoldCompareFloat(BuiltinInst *BI, BuiltinValueKind ID) {
627627
// x <= Inf
628628
m_BuiltinInst(BuiltinValueKind::FCMP_OLE,
629629
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
630-
// x != Inf
631-
m_BuiltinInst(BuiltinValueKind::FCMP_ONE,
632-
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
633-
// Inf != x
634-
m_BuiltinInst(BuiltinValueKind::FCMP_ONE,
635-
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other)),
636630
// Inf > x
637631
m_BuiltinInst(BuiltinValueKind::FCMP_UGT,
638632
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other)),
@@ -644,13 +638,7 @@ static SILValue constantFoldCompareFloat(BuiltinInst *BI, BuiltinValueKind ID) {
644638
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
645639
// x <= Inf
646640
m_BuiltinInst(BuiltinValueKind::FCMP_ULE,
647-
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
648-
// x != Inf
649-
m_BuiltinInst(BuiltinValueKind::FCMP_UNE,
650-
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
651-
// Inf != x
652-
m_BuiltinInst(BuiltinValueKind::FCMP_UNE,
653-
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other))))) {
641+
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg)))))) {
654642
APInt val = builtinArg->getValue();
655643
if (hasIEEEFloatPosInfBitRepr(val)) {
656644
// One of the operands is infinity, but unless the other operand is not
@@ -666,7 +654,7 @@ static SILValue constantFoldCompareFloat(BuiltinInst *BI, BuiltinValueKind ID) {
666654
}
667655
}
668656

669-
// Positive infinity is not less than, less than equal to or equal to anything
657+
// Positive infinity is not less than or less than equal to anything
670658
if (match(BI,
671659
m_CombineOr(
672660
// x > Inf
@@ -681,12 +669,6 @@ static SILValue constantFoldCompareFloat(BuiltinInst *BI, BuiltinValueKind ID) {
681669
// Inf <= x
682670
m_BuiltinInst(BuiltinValueKind::FCMP_OLE,
683671
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other)),
684-
// x == Inf
685-
m_BuiltinInst(BuiltinValueKind::FCMP_OEQ,
686-
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
687-
// Inf == x
688-
m_BuiltinInst(BuiltinValueKind::FCMP_OEQ,
689-
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other)),
690672
// x > Inf
691673
m_BuiltinInst(BuiltinValueKind::FCMP_UGT,
692674
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
@@ -698,12 +680,6 @@ static SILValue constantFoldCompareFloat(BuiltinInst *BI, BuiltinValueKind ID) {
698680
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other)),
699681
// Inf <= x
700682
m_BuiltinInst(BuiltinValueKind::FCMP_ULE,
701-
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other)),
702-
// x == Inf
703-
m_BuiltinInst(BuiltinValueKind::FCMP_UEQ,
704-
m_SILValue(Other), m_BitCast(m_IntegerLiteralInst(builtinArg))),
705-
// Inf == x
706-
m_BuiltinInst(BuiltinValueKind::FCMP_UEQ,
707683
m_BitCast(m_IntegerLiteralInst(builtinArg)), m_SILValue(Other))))) {
708684
APInt val = builtinArg->getValue();
709685
if (hasIEEEFloatPosInfBitRepr(val)) {

validation-test/SILOptimizer/constant_folded_fp_operations.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
270270
for op in FPOperation.allCases {
271271
for op1 in FPOperand.allCases {
272272
for op2 in FPOperand.allCases {
273+
if checkIfEqCmpBetweenInfAndNonInf(op: op, op1: op1, op2: op2) {
274+
continue
275+
}
273276
generateFuncDeclWithCheckDirectives(fpType: fpType, op: op, op1: op1, op2: op2, isopt: true)
274277
}
275278
}
@@ -282,6 +285,9 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
282285
for op in FPOperation.allCases {
283286
for op1 in FPOperand.allCases {
284287
for op2 in FPOperand.allCases {
288+
if checkIfEqCmpBetweenInfAndNonInf(op: op, op1: op1, op2: op2) {
289+
continue
290+
}
285291
generateFuncDeclWithCheckDirectives(fpType: fpType, op: op, op1: op1, op2: op2, isopt: false)
286292
}
287293
}
@@ -294,6 +300,9 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
294300
for op in FPOperation.allCases {
295301
for op1 in FPOperand.allCases {
296302
for op2 in FPOperand.allCases {
303+
if checkIfEqCmpBetweenInfAndNonInf(op: op, op1: op1, op2: op2) {
304+
continue
305+
}
297306
let comparisonFuncName = ["comparison", fpType.printable_name(), op.printable_name(), op1.printable_name(), op2.printable_name()].joined(separator: "_")
298307
let optFuncName = [optPrefix, fpType.printable_name(), op.printable_name(), op1.printable_name(), op2.printable_name()].joined(separator: "_")
299308
let unoptFuncName = [unoptPrefix, fpType.printable_name(), op.printable_name(), op1.printable_name(), op2.printable_name()].joined(separator: "_")
@@ -316,6 +325,9 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
316325
for op in FPOperation.allCases {
317326
for op1 in FPOperand.allCases {
318327
for op2 in FPOperand.allCases {
328+
if checkIfEqCmpBetweenInfAndNonInf(op: op, op1: op1, op2: op2) {
329+
continue
330+
}
319331
let comparison = resultComparisonCheck(fpType: fpType, op: op, op1: op1, op2: op2)
320332

321333
print("""
@@ -372,6 +384,20 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
372384
373385
""")
374386
}
387+
388+
// Equality comparisons b/w infinity and non-infinity are not constant folded.
389+
// In such comparisons, special floating point types - Float80 and Float16, may
390+
// come into play and pattern matching againt them complicates the constant folding
391+
// logic more than we'd like.
392+
private func checkIfEqCmpBetweenInfAndNonInf(op: FPOperation, op1: FPOperand, op2: FPOperand) -> Bool {
393+
if op == .Equal || op == .NotEqual {
394+
// If only one of the operands is infinity
395+
if (op1 == .Infinity || op2 == .Infinity) && !(op1 == .Infinity && op2 == .Infinity) {
396+
return true
397+
}
398+
}
399+
return false
400+
}
375401
}
376402

377403
////////////////// Arithmetic Operations Validator ///////////////////

0 commit comments

Comments
 (0)