File: FreezeIntDiv.cpp

package info (click to toggle)
intel-graphics-compiler2 2.22.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 107,676 kB
  • sloc: cpp: 809,645; lisp: 288,070; ansic: 16,397; python: 4,010; yacc: 2,588; lex: 1,666; pascal: 314; sh: 186; makefile: 38
file content (94 lines) | stat: -rw-r--r-- 2,988 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
/*========================== begin_copyright_notice ============================

Copyright (C) 2022-2023 Intel Corporation

SPDX-License-Identifier: MIT

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

#include "AdaptorCommon/FreezeIntDiv.hpp"
#include "Compiler/IGCPassSupport.h"

#include "common/LLVMWarningsPush.hpp"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/IRBuilder.h"
#include "common/LLVMWarningsPop.hpp"

using namespace llvm;

namespace IGC {

class FreezeIntDiv : public FunctionPass, public InstVisitor<FreezeIntDiv> {
public:
  static char ID;

  FreezeIntDiv() : FunctionPass(ID), changed(false) { initializeFreezeIntDivPass(*PassRegistry::getPassRegistry()); }

  bool runOnFunction(Function &F) override;

  StringRef getPassName() const override { return "FreezeIntDiv"; }

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

  void visitBinaryOperator(BinaryOperator &I);
  void freezeIntDiv(BinaryOperator &I);

private:
  bool changed;
};

char FreezeIntDiv::ID = 0;

#define PASS_FLAG "igc-freeze-int-div-pass"
#define PASS_DESCRIPTION "Freeze integer division"
#define PASS_CFG_ONLY false
#define PASS_ANALYSIS false
IGC_INITIALIZE_PASS_BEGIN(FreezeIntDiv, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
IGC_INITIALIZE_PASS_END(FreezeIntDiv, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)

FunctionPass *createFreezeIntDivPass() { return new FreezeIntDiv(); }

////////////////////////////////////////////////////////////////////////////
bool FreezeIntDiv::runOnFunction(Function &F) {
  changed = false;
  visit(F);
  return changed;
}

void FreezeIntDiv::freezeIntDiv(BinaryOperator &I) {
  llvm::IRBuilder<> builder(I.getNextNode());
  Value *FI = builder.CreateFreeze(&I, "freeze");
  I.replaceAllUsesWith(FI);
  cast<Instruction>(FI)->setOperand(0, &I);
}

void FreezeIntDiv::visitBinaryOperator(BinaryOperator &I) {
  switch (I.getOpcode()) {
  case Instruction::UDiv:
  case Instruction::SDiv:
  case Instruction::URem:
  case Instruction::SRem:
    // Stop propagation of poison values generated by LLVM in case of
    // integer division by zero. Use LLVM 10+ freeze instruction.
    {
      // In theory, we shouldn't have to check whether the input is, in
      // fact, poison/undef - the resulting freeze should simply resolve
      // to a no-op otherwise. However, until we resolve all freeze insts
      // in codegen, LLVM passes (InstCombine, GVN, SimplifyCFG, etc.)
      // can be sloppy with checking the operand's validity - as a
      // result, valuable optimizations can be skipped in some cases.
      // Therefore, minimize freeze emission for cases that are
      // guaranteed to be valid.
      auto *constDivisor = dyn_cast<ConstantInt>(I.getOperand(1));
      if (constDivisor && !constDivisor->isZero())
        break;
      freezeIntDiv(I);
      changed = true;
      break;
    }
  default:
    break;
  }
}

} // namespace IGC