File: ConstantEncoder.cpp

package info (click to toggle)
intel-graphics-compiler 1.0.12504.6-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 83,912 kB
  • sloc: cpp: 910,147; lisp: 202,655; ansic: 15,197; python: 4,025; yacc: 2,241; lex: 1,570; pascal: 244; sh: 104; makefile: 25
file content (143 lines) | stat: -rw-r--r-- 5,712 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*========================== begin_copyright_notice ============================

Copyright (C) 2021 Intel Corporation

SPDX-License-Identifier: MIT

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

#include "ConstantEncoder.h"

#include "vc/Support/GenXDiagnostic.h"
#include "vc/Utils/GenX/TypeSize.h"
#include "vc/Utils/General/Types.h"

#include "Probe/Assertion.h"
#include "llvmWrapper/IR/DerivedTypes.h"
#include "llvmWrapper/IR/Operator.h"

using namespace llvm;

static std::pair<APInt, std::vector<vISA::ZERelocEntry>>
encodeConstExprImpl(const llvm::GEPOperator &GEP, const DataLayout &DL) {
  IGC_ASSERT_MESSAGE(!isa<IGCLLVM::FixedVectorType>(GEP.getType()),
                     "vector gep is not yet supported");
  auto [Data, Relocs] = vc::encodeGlobalValueOrConstantExpression(
      *cast<Constant>(GEP.getPointerOperand()), DL);
  APInt Offset{Data.getBitWidth(), 0};
  bool Success = GEP.accumulateConstantOffset(DL, Offset);
  IGC_ASSERT_MESSAGE(Success,
                     "Offset must be constant for GEP constant expression");
  return {Data + Offset, Relocs};
}

static std::pair<APInt, std::vector<vISA::ZERelocEntry>>
encodeConstExprImpl(const PtrToIntOperator &P2I, const DataLayout &DL) {
  IGC_ASSERT_MESSAGE(!isa<IGCLLVM::FixedVectorType>(P2I.getType()),
                     "vector ptrtoint is not yet supported");
  auto [Data, Relocs] = vc::encodeGlobalValueOrConstantExpression(
      *cast<Constant>(P2I.getPointerOperand()), DL);
  auto DstSize = vc::getTypeSize(P2I.getType(), &DL);
  vc::TypeSizeWrapper SrcSize{Data.getBitWidth()};
  if (DstSize == SrcSize)
    // Nop ptrtoint just return the pointer operand encoding.
    return {Data, Relocs};

  if (DstSize > SrcSize)
    // zext ptrtoint case, just append zeros to data.
    return {Data.zext(DstSize.inBits()), Relocs};

  // The only supported case of truncation.
  if (DstSize.inBits() == 32 && SrcSize.inBits() == 64) {
    IGC_ASSERT_MESSAGE(
        Relocs.size() == 1 &&
            Relocs.front().r_type == vISA::GenRelocType::R_SYM_ADDR,
        "only 64-bit relocation is supported for a truncating ptrtoint");
    Relocs.front().r_type = vISA::GenRelocType::R_SYM_ADDR_32;
    return {Data.trunc(32), Relocs};
  }

  vc::diagnose(P2I.getContext(), "ConstantEncoder",
               "such ptrtoint constant expression is not supported", &P2I);
  return {Data, Relocs};
}

static std::pair<APInt, std::vector<vISA::ZERelocEntry>>
encodeConstExprImpl(const BitCastOperator &BC, const DataLayout &DL) {
  IGC_ASSERT_MESSAGE(!isa<IGCLLVM::FixedVectorType>(BC.getType()),
                     "vector bitcast is not yet supported");
  return vc::encodeGlobalValueOrConstantExpression(
      *cast<Constant>(BC.getOperand(0)), DL);
}

static std::pair<APInt, std::vector<vISA::ZERelocEntry>>
encodeConstExprImpl(const IGCLLVM::AddrSpaceCastOperator &ASC,
                    const DataLayout &DL) {
  IGC_ASSERT_MESSAGE(!isa<IGCLLVM::FixedVectorType>(ASC.getType()),
                     "vector addrspacecast is not yet supported");
  auto [Data, Relocs] = vc::encodeGlobalValueOrConstantExpression(
      *cast<Constant>(ASC.getPointerOperand()), DL);

  // FIXME: p3 to p4 cast should also be part of this case if we consider
  //        p3 higher bits are marked from the beginning. Alternatively those
  //        higher bits should be marked during addrspacecast, though it seems
  //        like a less efficient solution. Fix it once p3 design is settled.
  if (ASC.getSrcAddressSpace() == vc::AddrSpace::Global &&
      ASC.getDestAddressSpace() == vc::AddrSpace::Generic) {
    auto DstSize = vc::getTypeSize(ASC.getType(), &DL);
    auto SrcSize = vc::getTypeSize(ASC.getPointerOperand()->getType(), &DL);
    // Though not sure how generic pointer works for spir[32].
    IGC_ASSERT_MESSAGE(DstSize == SrcSize,
                       "Global and generic pointer sizes should match");
    return {Data, Relocs};
  }

  vc::diagnose(
      ASC.getContext(), "ConstantEncoder",
      "such addrspacecast constant expression is not supported or illegal",
      &ASC);
  return {Data, Relocs};
}

static std::pair<APInt, std::vector<vISA::ZERelocEntry>>
encodeGlobalValue(const GlobalValue &GV, const DataLayout &DL) {
  auto RelType = vISA::GenRelocType::R_NONE;
  auto Size = vc::getTypeSize(GV.getType(), &DL);
  switch (Size.inBits()) {
  case 32:
    RelType = vISA::GenRelocType::R_SYM_ADDR_32;
    break;
  case 64:
    RelType = vISA::GenRelocType::R_SYM_ADDR;
    break;
  default:
    report_fatal_error("Relocation of the provided pointer is not supported");
  }
  return {APInt::getNullValue(Size.inBits()),
          {vISA::ZERelocEntry{RelType, 0, GV.getName().str()}}};
}

static std::pair<APInt, std::vector<vISA::ZERelocEntry>>
encodeConstExpr(const ConstantExpr &CExpr, const DataLayout &DL) {
  switch (CExpr.getOpcode()) {
  case Instruction::GetElementPtr:
    return encodeConstExprImpl(cast<GEPOperator>(CExpr), DL);
  case Instruction::PtrToInt:
    return encodeConstExprImpl(cast<PtrToIntOperator>(CExpr), DL);
  case Instruction::BitCast:
    return encodeConstExprImpl(cast<BitCastOperator>(CExpr), DL);
  case Instruction::AddrSpaceCast:
    return encodeConstExprImpl(cast<IGCLLVM::AddrSpaceCastOperator>(CExpr), DL);
  default:
    IGC_ASSERT_MESSAGE(0, "Unsupported constant expression");
    return {APInt{}, {}};
  }
}

std::pair<APInt, std::vector<vISA::ZERelocEntry>>
vc::encodeGlobalValueOrConstantExpression(const Constant &C,
                                          const DataLayout &DL) {
  if (isa<GlobalValue>(C))
    return encodeGlobalValue(cast<GlobalValue>(C), DL);
  return encodeConstExpr(cast<ConstantExpr>(C), DL);
}