3
3
4
4
// 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
5
5
// 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
7
7
8
8
// REQUIRES: executable_test,optimized_stdlib
9
9
// REQUIRES: swift_in_compiler
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 ///////////////////
@@ -48,7 +56,7 @@ protocol FPOptimizedOpsValidator {
48
56
49
57
func optimizedFunDeclCheck( fpType: FPType , op: FPOperation , op1: FPOperand , op2: FPOperand ) -> String
50
58
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
52
60
}
53
61
54
62
////////////////// Common ///////////////////
@@ -244,16 +252,16 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
244
252
"""
245
253
}
246
254
247
- func resultComaparisonCheck (
255
+ func resultComparisonCheck (
248
256
fpType: FPType ,
249
257
op: FPOperation ,
250
258
op1: FPOperand ,
251
259
op2: FPOperand
252
260
) -> 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: " _ " )
254
262
255
263
return """
256
- // COMPARE-RESULT: [ \( resultVarName ) ] result equal? true
264
+ precondition( \( comparisonFuncName ) (), " \( comparisonFuncName ) returned false! " )
257
265
"""
258
266
}
259
267
@@ -287,15 +295,13 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
287
295
for op1 in FPOperand . allCases {
288
296
for op2 in FPOperand . allCases {
289
297
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: " _ " )
291
298
let optFuncName = [ optPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
292
299
let unoptFuncName = [ unoptPrefix, fpType. printable_name ( ) , op. printable_name ( ) , op1. printable_name ( ) , op2. printable_name ( ) ] . joined ( separator: " _ " )
293
300
294
301
print ( """
295
302
@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) ()
299
305
}
300
306
301
307
""" )
@@ -310,15 +316,12 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
310
316
for op in FPOperation . allCases {
311
317
for op1 in FPOperand . allCases {
312
318
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)
315
320
316
321
print ( """
317
- \( checkDirective)
318
- \( comparisonFuncName) ()
322
+ \( comparison)
319
323
320
324
""" )
321
-
322
325
}
323
326
}
324
327
}
@@ -369,4 +372,251 @@ struct FPConstantFoldedComparisonOpsValidator: FPOptimizedOpsValidator {
369
372
370
373
""" )
371
374
}
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