File: FastMathConstantHandling.cpp

package info (click to toggle)
intel-graphics-compiler2 2.16.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 106,644 kB
  • sloc: cpp: 805,640; lisp: 287,672; ansic: 16,414; python: 3,952; yacc: 2,588; lex: 1,666; pascal: 313; sh: 186; makefile: 35
file content (105 lines) | stat: -rw-r--r-- 3,287 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*========================== begin_copyright_notice ============================

Copyright (C) 2023 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

#include "common/LLVMWarningsPush.hpp"
#include <llvm/IR/Instructions.h>
#include <llvm/IR/InstVisitor.h>
#include <llvm/IR/Operator.h>
#include "common/LLVMWarningsPop.hpp"
#include "FastMathConstantHandling.h"
#include "Compiler/IGCPassSupport.h"
#include "common/igc_regkeys.hpp"

using namespace llvm;
namespace IGC {

class FastMathConstantHandling : public FunctionPass, public InstVisitor<FastMathConstantHandling> {
public:
  FastMathConstantHandling();
  ~FastMathConstantHandling() {}
  static char ID;
  bool runOnFunction(Function &F) override;
  void visitInstruction(Instruction &I);
  void visitFNeg(Instruction &I);
  void visitFDiv(Instruction &I);
  virtual llvm::StringRef getPassName() const override { return "Fast Math Constant Handling"; }

  void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); }
};

#define PASS_FLAG "FastMathConstantHandling"
#define PASS_DESC "Fast Math Constant Handling"
#define PASS_CFG_ONLY false
#define PASS_ANALYSIS false
IGC_INITIALIZE_PASS_BEGIN(FastMathConstantHandling, PASS_FLAG, PASS_DESC, PASS_CFG_ONLY, PASS_ANALYSIS)
IGC_INITIALIZE_PASS_END(FastMathConstantHandling, PASS_FLAG, PASS_DESC, PASS_CFG_ONLY, PASS_ANALYSIS)

char FastMathConstantHandling::ID = 0;

FastMathConstantHandling::FastMathConstantHandling() : FunctionPass(ID) {
  initializeFastMathConstantHandlingPass(*PassRegistry::getPassRegistry());
}

// This purpose of this pass is to catch bad fast flag management where we are seeing
// constants that are not matching the fast flags that are set on the instructions

void FastMathConstantHandling::visitInstruction(Instruction &I) {
  if (isa<FPMathOperator>(I)) {
    struct BoolSpecialConstants {
      bool hasInf = false;
      bool hasNan = false;
      bool hasNegZero = false;
    } BSC;

    for (auto &Op : I.operands()) {
      if (auto *fp_val = dyn_cast<llvm::ConstantFP>(Op)) {
        auto APF = fp_val->getValueAPF();
        BSC.hasInf |= APF.isInfinity();
        BSC.hasNan |= APF.isNaN();
        BSC.hasNegZero |= APF.isNegZero();
      }
    }

    if (BSC.hasInf)
      I.setHasNoInfs(false);

    if (BSC.hasNan)
      I.setHasNoNaNs(false);

    if (BSC.hasNegZero)
      I.setHasNoSignedZeros(false);
  }
}
#if LLVM_VERSION_MAJOR >= 10
void FastMathConstantHandling::visitFNeg(Instruction &I) {
  auto *fp_val = dyn_cast<llvm::ConstantFP>(I.getOperand(0));
  if (fp_val && fp_val->getValueAPF().isZero()) {
    for (auto *UI : I.users()) {
      if (isa<FPMathOperator>(UI))
        cast<Instruction>(UI)->setHasNoSignedZeros(false);
    }
  }
}
#endif

void FastMathConstantHandling::visitFDiv(Instruction &I) {
  if (auto *fp_val = dyn_cast<llvm::ConstantFP>(I.getOperand(1)); fp_val && fp_val->getValueAPF().isZero()) {
    I.setHasNoInfs(false);
  }
}

bool FastMathConstantHandling::runOnFunction(Function &F) {
  if (IGC_IS_FLAG_DISABLED(DisableFastMathConstantHandling)) {
    visit(F);
  }
  return true;
}

FunctionPass *createFastMathConstantHandling() { return new FastMathConstantHandling(); }

} // namespace IGC