33
44// RUN: %target-swift-frontend -emit-sil -O -suppress-warnings -verify %t/constant_folded_fp_operation_validation.swift 2>&1 | %FileCheck --check-prefix=CHECK-SIL %t/constant_folded_fp_operation_validation.swift
55// RUN: %target-build-swift -O -suppress-warnings %t/constant_folded_fp_operation_validation.swift -o %t/a.out
6- // RUN: %target-run %t/a.out | %FileCheck --check-prefix=COMPARE-RESULT %t/constant_folded_fp_operation_validation.swift
6+ // RUN: %target-run %t/a.out
77
88// REQUIRES: executable_test,optimized_stdlib
99// REQUIRES: swift_in_compiler
1313createTestFile ( )
1414
1515func createTestFile( ) {
16- let validator = FPConstantFoldedComparisonOpsValidator ( )
17- validator. generateOptimizedFuncDecls ( )
18- validator. generateUnoptimizedFuncDecls ( )
19- validator. generateComparisonFuncDecls ( )
20- validator. generateComparisonFuncCalls ( )
16+ generateOperandAccessors ( )
17+
18+ let cmpOpValidator = FPConstantFoldedComparisonOpsValidator ( )
19+ cmpOpValidator. generateOptimizedFuncDecls ( )
20+ cmpOpValidator. generateUnoptimizedFuncDecls ( )
21+ cmpOpValidator. generateComparisonFuncDecls ( )
22+ cmpOpValidator. generateComparisonFuncCalls ( )
23+
24+ let arithOpValidator = FPConstantFoldedArithmeticOpsValidator ( )
25+ arithOpValidator. generateOptimizedFuncDecls ( )
26+ arithOpValidator. generateUnoptimizedFuncDecls ( )
27+ arithOpValidator. generateComparisonFuncDecls ( )
28+ arithOpValidator. generateComparisonFuncCalls ( )
2129}
2230
2331/////////////////// Protocols ///////////////////
@@ -48,7 +56,7 @@ protocol FPOptimizedOpsValidator {
4856
4957 func optimizedFunDeclCheck( fpType: FPType , op: FPOperation , op1: FPOperand , op2: FPOperand ) -> String
5058 func unoptimizedFunDeclCheck( fpType: FPType , op: FPOperation , op1: FPOperand , op2: FPOperand ) -> String
51- func resultComaparisonCheck ( fpType: FPType , op: FPOperation , op1: FPOperand , op2: FPOperand ) -> String
59+ func resultComparisonCheck ( fpType: FPType , op: FPOperation , op1: FPOperand , op2: FPOperand ) -> String
5260}
5361
5462////////////////// Common ///////////////////
@@ -244,16 +252,16 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
244252 """
245253 }
246254
247- func resultComaparisonCheck (
255+ func resultComparisonCheck (
248256 fpType: FPType ,
249257 op: FPOperation ,
250258 op1: FPOperand ,
251259 op2: FPOperand
252260 ) -> String {
253- let resultVarName = [ " var " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
261+ let comparisonFuncName = [ " comparison " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
254262
255263 return """
256- // COMPARE-RESULT: [ \( resultVarName ) ] result equal? true
264+ precondition( \( comparisonFuncName ) (), " \( comparisonFuncName ) returned false! " )
257265 """
258266 }
259267
@@ -287,15 +295,13 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
287295 for op1 in FPOperand . allCases {
288296 for op2 in FPOperand . allCases {
289297 let comparisonFuncName = [ " comparison " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
290- let resultVarName = [ " var " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
291298 let optFuncName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
292299 let unoptFuncName = [ unoptPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
293300
294301 print ( """
295302 @inline(never) @_silgen_name( " \( comparisonFuncName) " ) @_optimize(none)
296- func \( comparisonFuncName) () {
297- let \( resultVarName) = \( optFuncName) () == \( unoptFuncName) ()
298- print( " [ \( resultVarName) ] result equal? \\ ( \( resultVarName) ) " )
303+ func \( comparisonFuncName) () -> Bool {
304+ return \( optFuncName) () == \( unoptFuncName) ()
299305 }
300306
301307 """ )
@@ -310,15 +316,12 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
310316 for op in FPOperation . allCases {
311317 for op1 in FPOperand . allCases {
312318 for op2 in FPOperand . allCases {
313- let comparisonFuncName = [ " comparison " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
314- let checkDirective = resultComaparisonCheck ( fpType: fpType, op: op, op1: op1, op2: op2)
319+ let comparison = resultComparisonCheck ( fpType: fpType, op: op, op1: op1, op2: op2)
315320
316321 print ( """
317- \( checkDirective)
318- \( comparisonFuncName) ()
322+ \( comparison)
319323
320324 """ )
321-
322325 }
323326 }
324327 }
@@ -369,4 +372,251 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
369372
370373 """ )
371374 }
372- }
375+ }
376+
377+ ////////////////// Arithmetic Operations Validator ///////////////////
378+
379+ struct FPConstantFoldedArithmeticOpsValidator : FPOptimizedOpsValidator {
380+ /// Type of floating points this validator deals with.
381+ enum _FpType : CaseIterable , Representable , Equatable {
382+ case Float
383+ case Double
384+
385+ func math_name( ) -> String {
386+ switch self {
387+ case . Float:
388+ return " Float "
389+ case . Double:
390+ return " Double "
391+ }
392+ }
393+
394+ func printable_name( ) -> String {
395+ switch self {
396+ case . Float:
397+ return " float "
398+ case . Double:
399+ return " double "
400+ }
401+ }
402+ }
403+
404+ /// Type of floating point operations this validator deals with.
405+ enum _FPOperation : CaseIterable , Representable , Equatable {
406+ case Add
407+ case Subtract
408+ case Multiply
409+ case Divide
410+
411+ func math_name( ) -> String {
412+ switch self {
413+ case . Add:
414+ return " + "
415+ case . Subtract:
416+ return " - "
417+ case . Multiply:
418+ return " * "
419+ case . Divide:
420+ return " / "
421+ }
422+ }
423+
424+ func printable_name( ) -> String {
425+ switch self {
426+ case . Add:
427+ return " add "
428+ case . Subtract:
429+ return " sub "
430+ case . Multiply:
431+ return " mul "
432+ case . Divide:
433+ return " div "
434+ }
435+ }
436+ }
437+
438+ /// Type of floating point operands this validator deals with.
439+ enum _FPOperand : CaseIterable , Representable , Equatable {
440+ case Zero
441+ case One
442+
443+ func math_name( ) -> String {
444+ switch self {
445+ case . Zero:
446+ return " 0.0 "
447+ case . One:
448+ return " 1.0 "
449+ }
450+ }
451+
452+ func printable_name( ) -> String {
453+ switch self {
454+ case . Zero:
455+ return " zero "
456+ case . One:
457+ return " one "
458+ }
459+ }
460+ }
461+
462+ private let optPrefix = " opt "
463+ private let unoptPrefix = " unopt "
464+
465+ /////////////////////// FPOptimizedOpsValidator Conformances ///////////////////////
466+ typealias FPType = _FpType
467+ typealias FPOperation = _FPOperation
468+ typealias FPOperand = _FPOperand
469+
470+ func optimizedFunDeclCheck(
471+ fpType: FPType ,
472+ op: FPOperation ,
473+ op1: FPOperand ,
474+ op2: FPOperand
475+ ) -> String {
476+ let funcName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
477+
478+ return """
479+ // CHECK-SIL-LABEL: sil hidden [noinline] @ \( funcName)
480+ // CHECK-SIL-NEXT: [global: ]
481+ // CHECK-SIL-NEXT: bb0:
482+ // CHECK-SIL-NOT: {{.*}}f \( op. printable_name ( ) ) {{.*}}
483+ // CHECK-SIL: } // end sil function ' \( funcName) '
484+ """
485+ }
486+
487+ func unoptimizedFunDeclCheck(
488+ fpType: FPType ,
489+ op: FPOperation ,
490+ op1: FPOperand ,
491+ op2: FPOperand
492+ ) -> String {
493+ let funcName = [ unoptPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
494+
495+ return """
496+ // CHECK-SIL-LABEL: sil hidden [noinline] [Onone] @ \( funcName)
497+ // CHECK-SIL-NEXT: bb0:
498+ // CHECK-SIL: {{.*}}f \( op. printable_name ( ) ) {{.*}}
499+ // CHECK-SIL: } // end sil function ' \( funcName) '
500+ """
501+ }
502+
503+ func resultComparisonCheck(
504+ fpType: FPType ,
505+ op: FPOperation ,
506+ op1: FPOperand ,
507+ op2: FPOperand
508+ ) -> String {
509+ let comparisonFuncName = [ " comparison " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
510+
511+ // 0.0 / 0.0 is NaN and Nan != Nan
512+ if op == . Divide && op1 == . Zero && op2 == . Zero {
513+ return """
514+ precondition(! \( comparisonFuncName) (), " \( comparisonFuncName) returned true. Expected false. " )
515+ """
516+ }
517+
518+ return """
519+ precondition( \( comparisonFuncName) (), " \( comparisonFuncName) returned false. Expected true. " )
520+ """
521+ }
522+
523+ func generateOptimizedFuncDecls( ) {
524+ for fpType in FPType . allCases {
525+ for op in FPOperation . allCases {
526+ for op1 in FPOperand . allCases {
527+ for op2 in FPOperand . allCases {
528+ generateFuncDeclWithCheckDirectives ( fpType: fpType, op: op, op1: op1, op2: op2, isopt: true )
529+ }
530+ }
531+ }
532+ }
533+ }
534+
535+ func generateUnoptimizedFuncDecls( ) {
536+ for fpType in FPType . allCases {
537+ for op in FPOperation . allCases {
538+ for op1 in FPOperand . allCases {
539+ for op2 in FPOperand . allCases {
540+ generateFuncDeclWithCheckDirectives ( fpType: fpType, op: op, op1: op1, op2: op2, isopt: false )
541+ }
542+ }
543+ }
544+ }
545+ }
546+
547+ func generateComparisonFuncDecls( ) {
548+ for fpType in FPType . allCases {
549+ for op in FPOperation . allCases {
550+ for op1 in FPOperand . allCases {
551+ for op2 in FPOperand . allCases {
552+ let comparisonFuncName = [ " comparison " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
553+ let optFuncName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
554+ let unoptFuncName = [ unoptPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
555+
556+ print ( """
557+ @inline(never) @_silgen_name( " \( comparisonFuncName) " ) @_optimize(none)
558+ func \( comparisonFuncName) () -> Bool {
559+ return \( optFuncName) () == \( unoptFuncName) ()
560+ }
561+
562+ """ )
563+ }
564+ }
565+ }
566+ }
567+ }
568+
569+ func generateComparisonFuncCalls( ) {
570+ for fpType in FPType . allCases {
571+ for op in FPOperation . allCases {
572+ for op1 in FPOperand . allCases {
573+ for op2 in FPOperand . allCases {
574+ let comparison = resultComparisonCheck ( fpType: fpType, op: op, op1: op1, op2: op2)
575+ print ( """
576+ \( comparison)
577+
578+ """ )
579+ }
580+ }
581+ }
582+ }
583+ }
584+
585+ /////////////////////// Utilities ///////////////////////
586+ private func generateFuncDeclWithCheckDirectives(
587+ fpType: FPType ,
588+ op: FPOperation ,
589+ op1: FPOperand ,
590+ op2: FPOperand ,
591+ isopt: Bool = false
592+ ) {
593+ var operand1 = op1. math_name ( )
594+ var operand2 = op2. math_name ( )
595+
596+ if !isopt {
597+ if fpType == . Double {
598+ operand1 = op1 == . Zero ? " zero_double() " : " one_double() "
599+ operand2 = op2 == . Zero ? " zero_double() " : " one_double() "
600+ } else {
601+ operand1 = op1 == . Zero ? " zero_float() " : " one_float() "
602+ operand2 = op2 == . Zero ? " zero_float() " : " one_float() "
603+ }
604+ }
605+
606+ let optPrefix = isopt ? optPrefix : unoptPrefix
607+ let optAttr = isopt ? " " : " @_optimize(none) "
608+ let funcName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
609+ let checkDirectives = isopt ?
610+ optimizedFunDeclCheck ( fpType: fpType, op: op, op1: op1, op2: op2) :
611+ unoptimizedFunDeclCheck ( fpType: fpType, op: op, op1: op1, op2: op2)
612+
613+ print ( """
614+ @inline(never) @_silgen_name( " \( funcName) " ) \( optAttr)
615+ func \( funcName) () -> \( fpType. math_name ( ) ) {
616+ return \( operand1) \( op. math_name ( ) ) \( operand2)
617+ }
618+ \( checkDirectives)
619+
620+ """ )
621+ }
622+ }
0 commit comments