summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeon/AMDILLiteralManager.cpp
blob: 43167f5700111d2321961ef2d2360e9c9a00f686 (plain)
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
//===--- AMDILLiteralManager.cpp - AMDIL Literal Manager Pass --*- C++ -*--===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//==-----------------------------------------------------------------------===//

#define DEBUG_TYPE "literal_manager"

#include "AMDIL.h"

#include "AMDILAlgorithms.tpp"
#include "AMDILKernelManager.h"
#include "AMDILMachineFunctionInfo.h"
#include "AMDILSubtarget.h"
#include "AMDILTargetMachine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;


// AMDIL Literal Manager traverses through all of the LOADCONST instructions and
// converts them from an immediate value to the literal index. The literal index
// is valid IL, but the immediate values are not. The Immediate values must be
// aggregated and declared for clarity and to reduce the number of literals that
// are used. It is also illegal to declare the same literal twice, so this keeps
// that from occuring.

namespace {
  class AMDILLiteralManager : public MachineFunctionPass {
  public:
    static char ID;
    AMDILLiteralManager(TargetMachine &tm AMDIL_OPT_LEVEL_DECL);
    virtual const char *getPassName() const;

    bool runOnMachineFunction(MachineFunction &MF);
  private:
    bool trackLiterals(MachineBasicBlock::iterator *bbb);
    TargetMachine &TM;
    const AMDILSubtarget *mSTM;
    AMDILKernelManager *mKM;
    AMDILMachineFunctionInfo *mMFI;
    int32_t mLitIdx;
    bool mChanged;
  };
  char AMDILLiteralManager::ID = 0;
}

namespace llvm {
  FunctionPass *
  createAMDILLiteralManager(TargetMachine &tm AMDIL_OPT_LEVEL_DECL) {
    return new AMDILLiteralManager(tm AMDIL_OPT_LEVEL_VAR);
  }
  
}

AMDILLiteralManager::AMDILLiteralManager(TargetMachine &tm
                                         AMDIL_OPT_LEVEL_DECL)
  : MachineFunctionPass(ID),
    TM(tm) {
}

bool AMDILLiteralManager::runOnMachineFunction(MachineFunction &MF) {
  mChanged = false;
  mMFI = MF.getInfo<AMDILMachineFunctionInfo>();
  const AMDILTargetMachine *amdtm =
    reinterpret_cast<const AMDILTargetMachine *>(&TM);
  mSTM = dynamic_cast<const AMDILSubtarget *>(amdtm->getSubtargetImpl());
  mKM = const_cast<AMDILKernelManager *>(mSTM->getKernelManager());
  safeNestedForEach(MF.begin(), MF.end(), MF.begin()->begin(),
      std::bind1st(std::mem_fun(&AMDILLiteralManager::trackLiterals), this));
  return mChanged;
}

bool AMDILLiteralManager::trackLiterals(MachineBasicBlock::iterator *bbb) {
  MachineInstr *MI = *bbb;
  uint32_t Opcode = MI->getOpcode();
  switch(Opcode) {
  default:
    return false;
  case AMDIL::LOADCONST_i8:
  case AMDIL::LOADCONST_i16:
  case AMDIL::LOADCONST_i32:
  case AMDIL::LOADCONST_i64:
  case AMDIL::LOADCONST_f32:
  case AMDIL::LOADCONST_f64:
    break;
  };
  MachineOperand &dstOp = MI->getOperand(0);
  MachineOperand &litOp = MI->getOperand(1);
  if (!litOp.isImm() && !litOp.isFPImm()) {
    return false;
  }
  if (!dstOp.isReg()) {
    return false;
  }
  // Change the literal to the correct index for each literal that is found.
  if (litOp.isImm()) {
    int64_t immVal = litOp.getImm();
    uint32_t idx = MI->getOpcode() == AMDIL::LOADCONST_i64 
                     ? mMFI->addi64Literal(immVal)
                     : mMFI->addi32Literal(static_cast<int>(immVal), Opcode);
    litOp.ChangeToImmediate(idx);
    return false;
  } 

  if (litOp.isFPImm()) {
    const ConstantFP *fpVal = litOp.getFPImm();
    uint32_t idx = MI->getOpcode() == AMDIL::LOADCONST_f64
                     ? mMFI->addf64Literal(fpVal)
                     : mMFI->addf32Literal(fpVal);
    litOp.ChangeToImmediate(idx);
    return false;
  }

  return false;
}

const char* AMDILLiteralManager::getPassName() const {
    return "AMDIL Constant Propagation";
}