1//=== HexagonSplitConst32AndConst64.cpp - split CONST32/Const64 into HI/LO ===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// When the compiler is invoked with no small data, for instance, with the -G0
11// command line option, then all CONST32_* opcodes should be broken down into
12// appropriate LO and HI instructions. This splitting is done by this pass.
13// The only reason this is not done in the DAG lowering itself is that there
14// is no simple way of getting the register allocator to allot the same hard
15// register to the result of LO and HI instructions. This pass is always
16// scheduled after register allocation.
17//
18//===----------------------------------------------------------------------===//
19
20#include "HexagonMachineFunctionInfo.h"
21#include "HexagonSubtarget.h"
22#include "HexagonTargetMachine.h"
23#include "HexagonTargetObjectFile.h"
24#include "llvm/CodeGen/LatencyPriorityQueue.h"
25#include "llvm/CodeGen/MachineDominators.h"
26#include "llvm/CodeGen/MachineFunctionPass.h"
27#include "llvm/CodeGen/MachineInstrBuilder.h"
28#include "llvm/CodeGen/MachineLoopInfo.h"
29#include "llvm/CodeGen/MachineRegisterInfo.h"
30#include "llvm/CodeGen/Passes.h"
31#include "llvm/CodeGen/ScheduleDAGInstrs.h"
32#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
33#include "llvm/CodeGen/SchedulerRegistry.h"
34#include "llvm/Support/Debug.h"
35#include "llvm/Support/MathExtras.h"
36#include "llvm/Target/TargetInstrInfo.h"
37#include "llvm/Target/TargetMachine.h"
38#include "llvm/Target/TargetRegisterInfo.h"
39
40using namespace llvm;
41
42#define DEBUG_TYPE "xfer"
43
44namespace llvm {
45  FunctionPass *createHexagonSplitConst32AndConst64();
46  void initializeHexagonSplitConst32AndConst64Pass(PassRegistry&);
47}
48
49namespace {
50
51class HexagonSplitConst32AndConst64 : public MachineFunctionPass {
52 public:
53    static char ID;
54    HexagonSplitConst32AndConst64() : MachineFunctionPass(ID) {}
55
56    const char *getPassName() const override {
57      return "Hexagon Split Const32s and Const64s";
58    }
59    bool runOnMachineFunction(MachineFunction &Fn) override;
60    MachineFunctionProperties getRequiredProperties() const override {
61      return MachineFunctionProperties().set(
62          MachineFunctionProperties::Property::AllVRegsAllocated);
63    }
64};
65
66
67char HexagonSplitConst32AndConst64::ID = 0;
68
69
70bool HexagonSplitConst32AndConst64::runOnMachineFunction(MachineFunction &Fn) {
71
72  const HexagonTargetObjectFile &TLOF =
73      *static_cast<const HexagonTargetObjectFile *>(
74          Fn.getTarget().getObjFileLowering());
75  if (TLOF.isSmallDataEnabled())
76    return true;
77
78  const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo();
79  const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo();
80
81  // Loop over all of the basic blocks
82  for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
83       MBBb != MBBe; ++MBBb) {
84    MachineBasicBlock *MBB = &*MBBb;
85    // Traverse the basic block
86    MachineBasicBlock::iterator MII = MBB->begin();
87    MachineBasicBlock::iterator MIE = MBB->end ();
88    while (MII != MIE) {
89      MachineInstr &MI = *MII;
90      int Opc = MI.getOpcode();
91      if (Opc == Hexagon::CONST32_Int_Real &&
92          MI.getOperand(1).isBlockAddress()) {
93        int DestReg = MI.getOperand(0).getReg();
94        MachineOperand &Symbol = MI.getOperand(1);
95
96        BuildMI(*MBB, MII, MI.getDebugLoc(), TII->get(Hexagon::LO), DestReg)
97            .addOperand(Symbol);
98        BuildMI(*MBB, MII, MI.getDebugLoc(), TII->get(Hexagon::HI), DestReg)
99            .addOperand(Symbol);
100        // MBB->erase returns the iterator to the next instruction, which is the
101        // one we want to process next
102        MII = MBB->erase(&MI);
103        continue;
104      }
105
106      else if (Opc == Hexagon::CONST32_Int_Real ||
107               Opc == Hexagon::CONST32_Float_Real) {
108        int DestReg = MI.getOperand(0).getReg();
109
110        // We have to convert an FP immediate into its corresponding integer
111        // representation
112        int64_t ImmValue;
113        if (Opc == Hexagon::CONST32_Float_Real) {
114          APFloat Val = MI.getOperand(1).getFPImm()->getValueAPF();
115          ImmValue = *Val.bitcastToAPInt().getRawData();
116        }
117        else
118          ImmValue = MI.getOperand(1).getImm();
119
120        BuildMI(*MBB, MII, MI.getDebugLoc(), TII->get(Hexagon::A2_tfrsi),
121                DestReg)
122            .addImm(ImmValue);
123        MII = MBB->erase(&MI);
124        continue;
125      }
126      else if (Opc == Hexagon::CONST64_Int_Real ||
127               Opc == Hexagon::CONST64_Float_Real) {
128        int DestReg = MI.getOperand(0).getReg();
129
130        // We have to convert an FP immediate into its corresponding integer
131        // representation
132        int64_t ImmValue;
133        if (Opc == Hexagon::CONST64_Float_Real) {
134          APFloat Val = MI.getOperand(1).getFPImm()->getValueAPF();
135          ImmValue = *Val.bitcastToAPInt().getRawData();
136        }
137        else
138          ImmValue = MI.getOperand(1).getImm();
139
140        unsigned DestLo = TRI->getSubReg(DestReg, Hexagon::subreg_loreg);
141        unsigned DestHi = TRI->getSubReg(DestReg, Hexagon::subreg_hireg);
142
143        int32_t LowWord = (ImmValue & 0xFFFFFFFF);
144        int32_t HighWord = (ImmValue >> 32) & 0xFFFFFFFF;
145
146        BuildMI(*MBB, MII, MI.getDebugLoc(), TII->get(Hexagon::A2_tfrsi),
147                DestLo)
148            .addImm(LowWord);
149        BuildMI(*MBB, MII, MI.getDebugLoc(), TII->get(Hexagon::A2_tfrsi),
150                DestHi)
151            .addImm(HighWord);
152        MII = MBB->erase(&MI);
153        continue;
154      }
155      ++MII;
156    }
157  }
158
159  return true;
160}
161
162}
163
164//===----------------------------------------------------------------------===//
165//                         Public Constructor Functions
166//===----------------------------------------------------------------------===//
167
168FunctionPass *
169llvm::createHexagonSplitConst32AndConst64() {
170  return new HexagonSplitConst32AndConst64();
171}
172