13
13
createTestFile ( )
14
14
15
15
func 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 ( )
21
29
}
22
30
23
31
/////////////////// Protocols ///////////////////
@@ -369,4 +377,257 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
369
377
370
378
""" )
371
379
}
372
- }
380
+ }
381
+
382
+ ////////////////// Arithmetic Operations Validator ///////////////////
383
+
384
+ struct FPConstantFoldedArithmeticOpsValidator : FPOptimizedOpsValidator {
385
+ /// Type of floating points this validator deals with.
386
+ enum _FpType : CaseIterable , Representable , Equatable {
387
+ case Float
388
+ case Double
389
+
390
+ func math_name( ) -> String {
391
+ switch self {
392
+ case . Float:
393
+ return " Float "
394
+ case . Double:
395
+ return " Double "
396
+ }
397
+ }
398
+
399
+ func printable_name( ) -> String {
400
+ switch self {
401
+ case . Float:
402
+ return " float "
403
+ case . Double:
404
+ return " double "
405
+ }
406
+ }
407
+ }
408
+
409
+ /// Type of floating point operations this validator deals with.
410
+ enum _FPOperation : CaseIterable , Representable , Equatable {
411
+ case Add
412
+ case Subtract
413
+ case Multiply
414
+ case Divide
415
+
416
+ func math_name( ) -> String {
417
+ switch self {
418
+ case . Add:
419
+ return " + "
420
+ case . Subtract:
421
+ return " - "
422
+ case . Multiply:
423
+ return " * "
424
+ case . Divide:
425
+ return " / "
426
+ }
427
+ }
428
+
429
+ func printable_name( ) -> String {
430
+ switch self {
431
+ case . Add:
432
+ return " add "
433
+ case . Subtract:
434
+ return " sub "
435
+ case . Multiply:
436
+ return " mul "
437
+ case . Divide:
438
+ return " div "
439
+ }
440
+ }
441
+ }
442
+
443
+ /// Type of floating point operands this validator deals with.
444
+ enum _FPOperand : CaseIterable , Representable , Equatable {
445
+ case Zero
446
+ case One
447
+
448
+ func math_name( ) -> String {
449
+ switch self {
450
+ case . Zero:
451
+ return " 0.0 "
452
+ case . One:
453
+ return " 1.0 "
454
+ }
455
+ }
456
+
457
+ func printable_name( ) -> String {
458
+ switch self {
459
+ case . Zero:
460
+ return " zero "
461
+ case . One:
462
+ return " one "
463
+ }
464
+ }
465
+ }
466
+
467
+ private let optPrefix = " opt "
468
+ private let unoptPrefix = " unopt "
469
+
470
+ /////////////////////// FPOptimizedOpsValidator Conformances ///////////////////////
471
+ typealias FPType = _FpType
472
+ typealias FPOperation = _FPOperation
473
+ typealias FPOperand = _FPOperand
474
+
475
+ func optimizedFunDeclCheck(
476
+ fpType: FPType ,
477
+ op: FPOperation ,
478
+ op1: FPOperand ,
479
+ op2: FPOperand
480
+ ) -> String {
481
+ let funcName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
482
+
483
+ return """
484
+ // CHECK-SIL-LABEL: sil hidden [noinline] @ \( funcName)
485
+ // CHECK-SIL-NEXT: [global: ]
486
+ // CHECK-SIL-NEXT: bb0:
487
+ // CHECK-SIL-NOT: {{.*}}f \( op. printable_name ( ) ) {{.*}}
488
+ // CHECK-SIL: } // end sil function ' \( funcName) '
489
+ """
490
+ }
491
+
492
+ func unoptimizedFunDeclCheck(
493
+ fpType: FPType ,
494
+ op: FPOperation ,
495
+ op1: FPOperand ,
496
+ op2: FPOperand
497
+ ) -> String {
498
+ let funcName = [ unoptPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
499
+
500
+ return """
501
+ // CHECK-SIL-LABEL: sil hidden [noinline] [Onone] @ \( funcName)
502
+ // CHECK-SIL-NEXT: bb0:
503
+ // CHECK-SIL: {{.*}}f \( op. printable_name ( ) ) {{.*}}
504
+ // CHECK-SIL: } // end sil function ' \( funcName) '
505
+ """
506
+ }
507
+
508
+ func resultComaparisonCheck(
509
+ fpType: FPType ,
510
+ op: FPOperation ,
511
+ op1: FPOperand ,
512
+ op2: FPOperand
513
+ ) -> String {
514
+ let resultVarName = [ " var " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
515
+
516
+ // 0.0 / 0.0 is NaN and Nan != Nan
517
+ if op == . Divide && op1 == . Zero && op2 == . Zero {
518
+ return """
519
+ // COMPARE-RESULT: [ \( resultVarName) ] result equal? false
520
+ """
521
+ }
522
+
523
+ return """
524
+ // COMPARE-RESULT: [ \( resultVarName) ] result equal? true
525
+ """
526
+ }
527
+
528
+ func generateOptimizedFuncDecls( ) {
529
+ for fpType in FPType . allCases {
530
+ for op in FPOperation . allCases {
531
+ for op1 in FPOperand . allCases {
532
+ for op2 in FPOperand . allCases {
533
+ generateFuncDeclWithCheckDirectives ( fpType: fpType, op: op, op1: op1, op2: op2, isopt: true )
534
+ }
535
+ }
536
+ }
537
+ }
538
+ }
539
+
540
+ func generateUnoptimizedFuncDecls( ) {
541
+ for fpType in FPType . allCases {
542
+ for op in FPOperation . allCases {
543
+ for op1 in FPOperand . allCases {
544
+ for op2 in FPOperand . allCases {
545
+ generateFuncDeclWithCheckDirectives ( fpType: fpType, op: op, op1: op1, op2: op2, isopt: false )
546
+ }
547
+ }
548
+ }
549
+ }
550
+ }
551
+
552
+ func generateComparisonFuncDecls( ) {
553
+ for fpType in FPType . allCases {
554
+ for op in FPOperation . allCases {
555
+ for op1 in FPOperand . allCases {
556
+ for op2 in FPOperand . allCases {
557
+ let comparisonFuncName = [ " comparison " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
558
+ let resultVarName = [ " var " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
559
+ let optFuncName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
560
+ let unoptFuncName = [ unoptPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
561
+
562
+ print ( """
563
+ @inline(never) @_silgen_name( " \( comparisonFuncName) " ) @_optimize(none)
564
+ func \( comparisonFuncName) () {
565
+ let \( resultVarName) = \( optFuncName) () == \( unoptFuncName) ()
566
+ print( " [ \( resultVarName) ] result equal? \\ ( \( resultVarName) ) " )
567
+ }
568
+
569
+ """ )
570
+ }
571
+ }
572
+ }
573
+ }
574
+ }
575
+
576
+ func generateComparisonFuncCalls( ) {
577
+ for fpType in FPType . allCases {
578
+ for op in FPOperation . allCases {
579
+ for op1 in FPOperand . allCases {
580
+ for op2 in FPOperand . allCases {
581
+ let comparisonFuncName = [ " comparison " , fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
582
+ let checkDirective = resultComaparisonCheck ( fpType: fpType, op: op, op1: op1, op2: op2)
583
+
584
+ print ( """
585
+ \( checkDirective)
586
+ \( comparisonFuncName) ()
587
+
588
+ """ )
589
+
590
+ }
591
+ }
592
+ }
593
+ }
594
+ }
595
+
596
+ /////////////////////// Utilities ///////////////////////
597
+ private func generateFuncDeclWithCheckDirectives(
598
+ fpType: FPType ,
599
+ op: FPOperation ,
600
+ op1: FPOperand ,
601
+ op2: FPOperand ,
602
+ isopt: Bool = false
603
+ ) {
604
+ var operand1 = op1. math_name ( )
605
+ var operand2 = op2. math_name ( )
606
+
607
+ if !isopt {
608
+ if fpType == . Double {
609
+ operand1 = op1 == . Zero ? " zero_double() " : " one_double() "
610
+ operand2 = op2 == . Zero ? " zero_double() " : " one_double() "
611
+ } else {
612
+ operand1 = op1 == . Zero ? " zero_float() " : " one_float() "
613
+ operand2 = op2 == . Zero ? " zero_float() " : " one_float() "
614
+ }
615
+ }
616
+
617
+ let optPrefix = isopt ? optPrefix : unoptPrefix
618
+ let optAttr = isopt ? " " : " @_optimize(none) "
619
+ let funcName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
620
+ let checkDirectives = isopt ?
621
+ optimizedFunDeclCheck ( fpType: fpType, op: op, op1: op1, op2: op2) :
622
+ unoptimizedFunDeclCheck ( fpType: fpType, op: op, op1: op1, op2: op2)
623
+
624
+ print ( """
625
+ @inline(never) @_silgen_name( " \( funcName) " ) \( optAttr)
626
+ func \( funcName) () -> \( fpType. math_name ( ) ) {
627
+ return \( operand1) \( op. math_name ( ) ) \( operand2)
628
+ }
629
+ \( checkDirectives)
630
+
631
+ """ )
632
+ }
633
+ }
0 commit comments