| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 1 | //===------- HexagonCopyToCombine.cpp - Hexagon Copy-To-Combine Pass ------===// | 
|  | 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 | // This pass replaces transfer instructions by combine instructions. | 
|  | 10 | // We walk along a basic block and look for two combinable instructions and try | 
|  | 11 | // to move them together. If we can move them next to each other we do so and | 
|  | 12 | // replace them with a combine instruction. | 
|  | 13 | //===----------------------------------------------------------------------===// | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 14 | #include "HexagonInstrInfo.h" | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 15 | #include "HexagonSubtarget.h" | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 16 | #include "llvm/ADT/DenseMap.h" | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 17 | #include "llvm/ADT/DenseSet.h" | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 18 | #include "llvm/CodeGen/MachineBasicBlock.h" | 
|  | 19 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 20 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | 21 | #include "llvm/CodeGen/MachineInstr.h" | 
|  | 22 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/Passes.h" | 
| Chandler Carruth | 6bda14b | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 24 | #include "llvm/PassSupport.h" | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 25 | #include "llvm/Support/CodeGen.h" | 
|  | 26 | #include "llvm/Support/CommandLine.h" | 
|  | 27 | #include "llvm/Support/Debug.h" | 
|  | 28 | #include "llvm/Support/raw_ostream.h" | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 29 | #include "llvm/Target/TargetRegisterInfo.h" | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 30 |  | 
|  | 31 | using namespace llvm; | 
|  | 32 |  | 
| Chandler Carruth | 84e68b2 | 2014-04-22 02:41:26 +0000 | [diff] [blame] | 33 | #define DEBUG_TYPE "hexagon-copy-combine" | 
|  | 34 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 35 | static | 
|  | 36 | cl::opt<bool> IsCombinesDisabled("disable-merge-into-combines", | 
|  | 37 | cl::Hidden, cl::ZeroOrMore, | 
|  | 38 | cl::init(false), | 
|  | 39 | cl::desc("Disable merging into combines")); | 
|  | 40 | static | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 41 | cl::opt<bool> IsConst64Disabled("disable-const64", | 
|  | 42 | cl::Hidden, cl::ZeroOrMore, | 
|  | 43 | cl::init(false), | 
|  | 44 | cl::desc("Disable generation of const64")); | 
|  | 45 | static | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 46 | cl::opt<unsigned> | 
|  | 47 | MaxNumOfInstsBetweenNewValueStoreAndTFR("max-num-inst-between-tfr-and-nv-store", | 
|  | 48 | cl::Hidden, cl::init(4), | 
|  | 49 | cl::desc("Maximum distance between a tfr feeding a store we " | 
|  | 50 | "consider the store still to be newifiable")); | 
|  | 51 |  | 
|  | 52 | namespace llvm { | 
| Colin LeMahieu | 56efafc | 2015-06-15 19:05:35 +0000 | [diff] [blame] | 53 | FunctionPass *createHexagonCopyToCombine(); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 54 | void initializeHexagonCopyToCombinePass(PassRegistry&); | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 |  | 
|  | 58 | namespace { | 
|  | 59 |  | 
|  | 60 | class HexagonCopyToCombine : public MachineFunctionPass  { | 
|  | 61 | const HexagonInstrInfo *TII; | 
|  | 62 | const TargetRegisterInfo *TRI; | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 63 | const HexagonSubtarget *ST; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 64 | bool ShouldCombineAggressively; | 
|  | 65 |  | 
|  | 66 | DenseSet<MachineInstr *> PotentiallyNewifiableTFR; | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 67 | SmallVector<MachineInstr *, 8> DbgMItoMove; | 
|  | 68 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 69 | public: | 
|  | 70 | static char ID; | 
|  | 71 |  | 
|  | 72 | HexagonCopyToCombine() : MachineFunctionPass(ID) { | 
|  | 73 | initializeHexagonCopyToCombinePass(*PassRegistry::getPassRegistry()); | 
|  | 74 | } | 
|  | 75 |  | 
| Craig Topper | 906c2cd | 2014-04-29 07:58:16 +0000 | [diff] [blame] | 76 | void getAnalysisUsage(AnalysisUsage &AU) const override { | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 77 | MachineFunctionPass::getAnalysisUsage(AU); | 
|  | 78 | } | 
|  | 79 |  | 
| Mehdi Amini | 117296c | 2016-10-01 02:56:57 +0000 | [diff] [blame] | 80 | StringRef getPassName() const override { | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 81 | return "Hexagon Copy-To-Combine Pass"; | 
|  | 82 | } | 
|  | 83 |  | 
| Craig Topper | 906c2cd | 2014-04-29 07:58:16 +0000 | [diff] [blame] | 84 | bool runOnMachineFunction(MachineFunction &Fn) override; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 85 |  | 
| Derek Schuff | 1dbf7a5 | 2016-04-04 17:09:25 +0000 | [diff] [blame] | 86 | MachineFunctionProperties getRequiredProperties() const override { | 
|  | 87 | return MachineFunctionProperties().set( | 
| Matthias Braun | 1eb4736 | 2016-08-25 01:27:13 +0000 | [diff] [blame] | 88 | MachineFunctionProperties::Property::NoVRegs); | 
| Derek Schuff | 1dbf7a5 | 2016-04-04 17:09:25 +0000 | [diff] [blame] | 89 | } | 
|  | 90 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 91 | private: | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 92 | MachineInstr *findPairable(MachineInstr &I1, bool &DoInsertAtI1, | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 93 | bool AllowC64); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 94 |  | 
|  | 95 | void findPotentialNewifiableTFRs(MachineBasicBlock &); | 
|  | 96 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 97 | void combine(MachineInstr &I1, MachineInstr &I2, | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 98 | MachineBasicBlock::iterator &MI, bool DoInsertAtI1, | 
|  | 99 | bool OptForSize); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 100 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 101 | bool isSafeToMoveTogether(MachineInstr &I1, MachineInstr &I2, | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 102 | unsigned I1DestReg, unsigned I2DestReg, | 
|  | 103 | bool &DoInsertAtI1); | 
|  | 104 |  | 
|  | 105 | void emitCombineRR(MachineBasicBlock::iterator &Before, unsigned DestReg, | 
|  | 106 | MachineOperand &HiOperand, MachineOperand &LoOperand); | 
|  | 107 |  | 
|  | 108 | void emitCombineRI(MachineBasicBlock::iterator &Before, unsigned DestReg, | 
|  | 109 | MachineOperand &HiOperand, MachineOperand &LoOperand); | 
|  | 110 |  | 
|  | 111 | void emitCombineIR(MachineBasicBlock::iterator &Before, unsigned DestReg, | 
|  | 112 | MachineOperand &HiOperand, MachineOperand &LoOperand); | 
|  | 113 |  | 
|  | 114 | void emitCombineII(MachineBasicBlock::iterator &Before, unsigned DestReg, | 
|  | 115 | MachineOperand &HiOperand, MachineOperand &LoOperand); | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 116 |  | 
|  | 117 | void emitConst64(MachineBasicBlock::iterator &Before, unsigned DestReg, | 
|  | 118 | MachineOperand &HiOperand, MachineOperand &LoOperand); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 119 | }; | 
|  | 120 |  | 
|  | 121 | } // End anonymous namespace. | 
|  | 122 |  | 
|  | 123 | char HexagonCopyToCombine::ID = 0; | 
|  | 124 |  | 
|  | 125 | INITIALIZE_PASS(HexagonCopyToCombine, "hexagon-copy-combine", | 
|  | 126 | "Hexagon Copy-To-Combine Pass", false, false) | 
|  | 127 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 128 | static bool isCombinableInstType(MachineInstr &MI, const HexagonInstrInfo *TII, | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 129 | bool ShouldCombineAggressively) { | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 130 | switch (MI.getOpcode()) { | 
| Colin LeMahieu | 4af437f | 2014-12-09 20:23:30 +0000 | [diff] [blame] | 131 | case Hexagon::A2_tfr: { | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 132 | // A COPY instruction can be combined if its arguments are IntRegs (32bit). | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 133 | const MachineOperand &Op0 = MI.getOperand(0); | 
|  | 134 | const MachineOperand &Op1 = MI.getOperand(1); | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 135 | assert(Op0.isReg() && Op1.isReg()); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 136 |  | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 137 | unsigned DestReg = Op0.getReg(); | 
|  | 138 | unsigned SrcReg = Op1.getReg(); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 139 | return Hexagon::IntRegsRegClass.contains(DestReg) && | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 140 | Hexagon::IntRegsRegClass.contains(SrcReg); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 141 | } | 
|  | 142 |  | 
| Colin LeMahieu | 4af437f | 2014-12-09 20:23:30 +0000 | [diff] [blame] | 143 | case Hexagon::A2_tfrsi: { | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 144 | // A transfer-immediate can be combined if its argument is a signed 8bit | 
|  | 145 | // value. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 146 | const MachineOperand &Op0 = MI.getOperand(0); | 
|  | 147 | const MachineOperand &Op1 = MI.getOperand(1); | 
| Colin LeMahieu | 2efa2d0 | 2015-03-09 21:48:13 +0000 | [diff] [blame] | 148 | assert(Op0.isReg()); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 149 |  | 
| Colin LeMahieu | 2efa2d0 | 2015-03-09 21:48:13 +0000 | [diff] [blame] | 150 | unsigned DestReg = Op0.getReg(); | 
|  | 151 | // Ensure that TargetFlags are MO_NO_FLAG for a global. This is a | 
|  | 152 | // workaround for an ABI bug that prevents GOT relocations on combine | 
|  | 153 | // instructions | 
|  | 154 | if (!Op1.isImm() && Op1.getTargetFlags() != HexagonII::MO_NO_FLAG) | 
|  | 155 | return false; | 
|  | 156 |  | 
|  | 157 | // Only combine constant extended A2_tfrsi if we are in aggressive mode. | 
|  | 158 | bool NotExt = Op1.isImm() && isInt<8>(Op1.getImm()); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 159 | return Hexagon::IntRegsRegClass.contains(DestReg) && | 
| Colin LeMahieu | 2efa2d0 | 2015-03-09 21:48:13 +0000 | [diff] [blame] | 160 | (ShouldCombineAggressively || NotExt); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 161 | } | 
|  | 162 |  | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 163 | case Hexagon::V6_vassign: | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 164 | return true; | 
|  | 165 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 166 | default: | 
|  | 167 | break; | 
|  | 168 | } | 
|  | 169 |  | 
|  | 170 | return false; | 
|  | 171 | } | 
|  | 172 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 173 | template <unsigned N> static bool isGreaterThanNBitTFRI(const MachineInstr &I) { | 
|  | 174 | if (I.getOpcode() == Hexagon::TFRI64_V4 || | 
|  | 175 | I.getOpcode() == Hexagon::A2_tfrsi) { | 
|  | 176 | const MachineOperand &Op = I.getOperand(1); | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 177 | return !Op.isImm() || !isInt<N>(Op.getImm()); | 
|  | 178 | } | 
|  | 179 | return false; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 180 | } | 
|  | 181 |  | 
|  | 182 | /// areCombinableOperations - Returns true if the two instruction can be merge | 
|  | 183 | /// into a combine (ignoring register constraints). | 
|  | 184 | static bool areCombinableOperations(const TargetRegisterInfo *TRI, | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 185 | MachineInstr &HighRegInst, | 
|  | 186 | MachineInstr &LowRegInst, bool AllowC64) { | 
|  | 187 | unsigned HiOpc = HighRegInst.getOpcode(); | 
|  | 188 | unsigned LoOpc = LowRegInst.getOpcode(); | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 189 |  | 
|  | 190 | auto verifyOpc = [](unsigned Opc) -> void { | 
|  | 191 | switch (Opc) { | 
|  | 192 | case Hexagon::A2_tfr: | 
|  | 193 | case Hexagon::A2_tfrsi: | 
|  | 194 | case Hexagon::V6_vassign: | 
|  | 195 | break; | 
|  | 196 | default: | 
|  | 197 | llvm_unreachable("Unexpected opcode"); | 
|  | 198 | } | 
|  | 199 | }; | 
|  | 200 | verifyOpc(HiOpc); | 
|  | 201 | verifyOpc(LoOpc); | 
|  | 202 |  | 
|  | 203 | if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign) | 
|  | 204 | return HiOpc == LoOpc; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 205 |  | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 206 | if (!AllowC64) { | 
|  | 207 | // There is no combine of two constant extended values. | 
|  | 208 | if (isGreaterThanNBitTFRI<8>(HighRegInst) && | 
|  | 209 | isGreaterThanNBitTFRI<6>(LowRegInst)) | 
|  | 210 | return false; | 
|  | 211 | } | 
|  | 212 |  | 
|  | 213 | // There is a combine of two constant extended values into CONST64, | 
|  | 214 | // provided both constants are true immediates. | 
|  | 215 | if (isGreaterThanNBitTFRI<16>(HighRegInst) && | 
|  | 216 | isGreaterThanNBitTFRI<16>(LowRegInst)) | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 217 | return (HighRegInst.getOperand(1).isImm() && | 
|  | 218 | LowRegInst.getOperand(1).isImm()); | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 219 |  | 
|  | 220 | // There is no combine of two constant extended values, unless handled above | 
|  | 221 | // Make both 8-bit size checks to allow both combine (#,##) and combine(##,#) | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 222 | if (isGreaterThanNBitTFRI<8>(HighRegInst) && | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 223 | isGreaterThanNBitTFRI<8>(LowRegInst)) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 224 | return false; | 
|  | 225 |  | 
|  | 226 | return true; | 
|  | 227 | } | 
|  | 228 |  | 
|  | 229 | static bool isEvenReg(unsigned Reg) { | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 230 | assert(TargetRegisterInfo::isPhysicalRegister(Reg)); | 
|  | 231 | if (Hexagon::IntRegsRegClass.contains(Reg)) | 
|  | 232 | return (Reg - Hexagon::R0) % 2 == 0; | 
| Krzysztof Parzyszek | 5577297 | 2017-09-15 15:46:05 +0000 | [diff] [blame] | 233 | if (Hexagon::HvxVRRegClass.contains(Reg)) | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 234 | return (Reg - Hexagon::V0) % 2 == 0; | 
|  | 235 | llvm_unreachable("Invalid register"); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 236 | } | 
|  | 237 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 238 | static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled) { | 
|  | 239 | for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { | 
|  | 240 | MachineOperand &Op = MI.getOperand(I); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 241 | if (!Op.isReg() || Op.getReg() != RegNotKilled || !Op.isKill()) | 
|  | 242 | continue; | 
|  | 243 | Op.setIsKill(false); | 
|  | 244 | } | 
|  | 245 | } | 
|  | 246 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 247 | /// Returns true if it is unsafe to move a copy instruction from \p UseReg to | 
|  | 248 | /// \p DestReg over the instruction \p MI. | 
|  | 249 | static bool isUnsafeToMoveAcross(MachineInstr &MI, unsigned UseReg, | 
|  | 250 | unsigned DestReg, | 
|  | 251 | const TargetRegisterInfo *TRI) { | 
|  | 252 | return (UseReg && (MI.modifiesRegister(UseReg, TRI))) || | 
|  | 253 | MI.modifiesRegister(DestReg, TRI) || MI.readsRegister(DestReg, TRI) || | 
| Krzysztof Parzyszek | 709e4f9 | 2017-08-10 15:00:30 +0000 | [diff] [blame] | 254 | MI.hasUnmodeledSideEffects() || MI.isInlineAsm() || | 
|  | 255 | MI.isMetaInstruction(); | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 256 | } | 
|  | 257 |  | 
|  | 258 | static unsigned UseReg(const MachineOperand& MO) { | 
|  | 259 | return MO.isReg() ? MO.getReg() : 0; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 260 | } | 
|  | 261 |  | 
|  | 262 | /// isSafeToMoveTogether - Returns true if it is safe to move I1 next to I2 such | 
|  | 263 | /// that the two instructions can be paired in a combine. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 264 | bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1, | 
|  | 265 | MachineInstr &I2, | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 266 | unsigned I1DestReg, | 
|  | 267 | unsigned I2DestReg, | 
|  | 268 | bool &DoInsertAtI1) { | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 269 | unsigned I2UseReg = UseReg(I2.getOperand(1)); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 270 |  | 
|  | 271 | // It is not safe to move I1 and I2 into one combine if I2 has a true | 
|  | 272 | // dependence on I1. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 273 | if (I2UseReg && I1.modifiesRegister(I2UseReg, TRI)) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 274 | return false; | 
|  | 275 |  | 
|  | 276 | bool isSafe = true; | 
|  | 277 |  | 
|  | 278 | // First try to move I2 towards I1. | 
|  | 279 | { | 
|  | 280 | // A reverse_iterator instantiated like below starts before I2, and I1 | 
|  | 281 | // respectively. | 
|  | 282 | // Look at instructions I in between I2 and (excluding) I1. | 
|  | 283 | MachineBasicBlock::reverse_iterator I(I2), | 
|  | 284 | End = --(MachineBasicBlock::reverse_iterator(I1)); | 
|  | 285 | // At 03 we got better results (dhrystone!) by being more conservative. | 
|  | 286 | if (!ShouldCombineAggressively) | 
|  | 287 | End = MachineBasicBlock::reverse_iterator(I1); | 
|  | 288 | // If I2 kills its operand and we move I2 over an instruction that also | 
|  | 289 | // uses I2's use reg we need to modify that (first) instruction to now kill | 
|  | 290 | // this reg. | 
|  | 291 | unsigned KilledOperand = 0; | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 292 | if (I2.killsRegister(I2UseReg)) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 293 | KilledOperand = I2UseReg; | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 294 | MachineInstr *KillingInstr = nullptr; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 295 |  | 
|  | 296 | for (; I != End; ++I) { | 
|  | 297 | // If the intervening instruction I: | 
|  | 298 | //   * modifies I2's use reg | 
|  | 299 | //   * modifies I2's def reg | 
|  | 300 | //   * reads I2's def reg | 
|  | 301 | //   * or has unmodelled side effects | 
|  | 302 | // we can't move I2 across it. | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 303 | if (I->isDebugValue()) | 
|  | 304 | continue; | 
|  | 305 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 306 | if (isUnsafeToMoveAcross(*I, I2UseReg, I2DestReg, TRI)) { | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 307 | isSafe = false; | 
|  | 308 | break; | 
|  | 309 | } | 
|  | 310 |  | 
|  | 311 | // Update first use of the killed operand. | 
|  | 312 | if (!KillingInstr && KilledOperand && | 
|  | 313 | I->readsRegister(KilledOperand, TRI)) | 
|  | 314 | KillingInstr = &*I; | 
|  | 315 | } | 
|  | 316 | if (isSafe) { | 
|  | 317 | // Update the intermediate instruction to with the kill flag. | 
|  | 318 | if (KillingInstr) { | 
|  | 319 | bool Added = KillingInstr->addRegisterKilled(KilledOperand, TRI, true); | 
| Alp Toker | cb40291 | 2014-01-24 17:20:08 +0000 | [diff] [blame] | 320 | (void)Added; // suppress compiler warning | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 321 | assert(Added && "Must successfully update kill flag"); | 
|  | 322 | removeKillInfo(I2, KilledOperand); | 
|  | 323 | } | 
|  | 324 | DoInsertAtI1 = true; | 
|  | 325 | return true; | 
|  | 326 | } | 
|  | 327 | } | 
|  | 328 |  | 
|  | 329 | // Try to move I1 towards I2. | 
|  | 330 | { | 
|  | 331 | // Look at instructions I in between I1 and (excluding) I2. | 
|  | 332 | MachineBasicBlock::iterator I(I1), End(I2); | 
|  | 333 | // At O3 we got better results (dhrystone) by being more conservative here. | 
|  | 334 | if (!ShouldCombineAggressively) | 
| Benjamin Kramer | b6d0bd4 | 2014-03-02 12:27:27 +0000 | [diff] [blame] | 335 | End = std::next(MachineBasicBlock::iterator(I2)); | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 336 | unsigned I1UseReg = UseReg(I1.getOperand(1)); | 
| Jyotsna Verma | cceafb2 | 2013-05-28 19:01:45 +0000 | [diff] [blame] | 337 | // Track killed operands. If we move across an instruction that kills our | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 338 | // operand, we need to update the kill information on the moved I1. It kills | 
|  | 339 | // the operand now. | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 340 | MachineInstr *KillingInstr = nullptr; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 341 | unsigned KilledOperand = 0; | 
|  | 342 |  | 
|  | 343 | while(++I != End) { | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 344 | MachineInstr &MI = *I; | 
|  | 345 | // If the intervening instruction MI: | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 346 | //   * modifies I1's use reg | 
|  | 347 | //   * modifies I1's def reg | 
|  | 348 | //   * reads I1's def reg | 
|  | 349 | //   * or has unmodelled side effects | 
|  | 350 | //   We introduce this special case because llvm has no api to remove a | 
|  | 351 | //   kill flag for a register (a removeRegisterKilled() analogous to | 
|  | 352 | //   addRegisterKilled) that handles aliased register correctly. | 
|  | 353 | //   * or has a killed aliased register use of I1's use reg | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 354 | //           %D4<def> = A2_tfrpi 16 | 
|  | 355 | //           %R6<def> = A2_tfr %R9 | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 356 | //           %R8<def> = KILL %R8, %D4<imp-use,kill> | 
|  | 357 | //      If we want to move R6 = across the KILL instruction we would have | 
|  | 358 | //      to remove the %D4<imp-use,kill> operand. For now, we are | 
|  | 359 | //      conservative and disallow the move. | 
|  | 360 | // we can't move I1 across it. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 361 | if (MI.isDebugValue()) { | 
|  | 362 | if (MI.readsRegister(I1DestReg, TRI)) // Move this instruction after I2. | 
|  | 363 | DbgMItoMove.push_back(&MI); | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 364 | continue; | 
|  | 365 | } | 
|  | 366 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 367 | if (isUnsafeToMoveAcross(MI, I1UseReg, I1DestReg, TRI) || | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 368 | // Check for an aliased register kill. Bail out if we see one. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 369 | (!MI.killsRegister(I1UseReg) && MI.killsRegister(I1UseReg, TRI))) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 370 | return false; | 
|  | 371 |  | 
|  | 372 | // Check for an exact kill (registers match). | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 373 | if (I1UseReg && MI.killsRegister(I1UseReg)) { | 
| Craig Topper | e73658d | 2014-04-28 04:05:08 +0000 | [diff] [blame] | 374 | assert(!KillingInstr && "Should only see one killing instruction"); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 375 | KilledOperand = I1UseReg; | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 376 | KillingInstr = &MI; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 377 | } | 
|  | 378 | } | 
|  | 379 | if (KillingInstr) { | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 380 | removeKillInfo(*KillingInstr, KilledOperand); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 381 | // Update I1 to set the kill flag. This flag will later be picked up by | 
|  | 382 | // the new COMBINE instruction. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 383 | bool Added = I1.addRegisterKilled(KilledOperand, TRI); | 
| Alp Toker | cb40291 | 2014-01-24 17:20:08 +0000 | [diff] [blame] | 384 | (void)Added; // suppress compiler warning | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 385 | assert(Added && "Must successfully update kill flag"); | 
|  | 386 | } | 
|  | 387 | DoInsertAtI1 = false; | 
|  | 388 | } | 
|  | 389 |  | 
|  | 390 | return true; | 
|  | 391 | } | 
|  | 392 |  | 
|  | 393 | /// findPotentialNewifiableTFRs - Finds tranfers that feed stores that could be | 
|  | 394 | /// newified. (A use of a 64 bit register define can not be newified) | 
|  | 395 | void | 
|  | 396 | HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) { | 
|  | 397 | DenseMap<unsigned, MachineInstr *> LastDef; | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 398 | for (MachineInstr &MI : BB) { | 
|  | 399 | if (MI.isDebugValue()) | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 400 | continue; | 
|  | 401 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 402 | // Mark TFRs that feed a potential new value store as such. | 
| Krzysztof Parzyszek | f0b34a5 | 2016-07-29 21:49:42 +0000 | [diff] [blame] | 403 | if (TII->mayBeNewStore(MI)) { | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 404 | // Look for uses of TFR instructions. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 405 | for (unsigned OpdIdx = 0, OpdE = MI.getNumOperands(); OpdIdx != OpdE; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 406 | ++OpdIdx) { | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 407 | MachineOperand &Op = MI.getOperand(OpdIdx); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 408 |  | 
|  | 409 | // Skip over anything except register uses. | 
|  | 410 | if (!Op.isReg() || !Op.isUse() || !Op.getReg()) | 
|  | 411 | continue; | 
|  | 412 |  | 
|  | 413 | // Look for the defining instruction. | 
|  | 414 | unsigned Reg = Op.getReg(); | 
|  | 415 | MachineInstr *DefInst = LastDef[Reg]; | 
|  | 416 | if (!DefInst) | 
|  | 417 | continue; | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 418 | if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively)) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 419 | continue; | 
|  | 420 |  | 
|  | 421 | // Only close newifiable stores should influence the decision. | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 422 | // Ignore the debug instructions in between. | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 423 | MachineBasicBlock::iterator It(DefInst); | 
|  | 424 | unsigned NumInstsToDef = 0; | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 425 | while (&*It != &MI) { | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 426 | if (!It->isDebugValue()) | 
|  | 427 | ++NumInstsToDef; | 
| Krzysztof Parzyszek | 14f9535e | 2016-01-21 12:45:17 +0000 | [diff] [blame] | 428 | ++It; | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 429 | } | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 430 |  | 
|  | 431 | if (NumInstsToDef > MaxNumOfInstsBetweenNewValueStoreAndTFR) | 
|  | 432 | continue; | 
|  | 433 |  | 
|  | 434 | PotentiallyNewifiableTFR.insert(DefInst); | 
|  | 435 | } | 
|  | 436 | // Skip to next instruction. | 
|  | 437 | continue; | 
|  | 438 | } | 
|  | 439 |  | 
|  | 440 | // Put instructions that last defined integer or double registers into the | 
|  | 441 | // map. | 
| Krzysztof Parzyszek | 1aaf41a | 2017-02-17 22:14:51 +0000 | [diff] [blame] | 442 | for (MachineOperand &Op : MI.operands()) { | 
|  | 443 | if (Op.isReg()) { | 
|  | 444 | if (!Op.isDef() || !Op.getReg()) | 
|  | 445 | continue; | 
|  | 446 | unsigned Reg = Op.getReg(); | 
|  | 447 | if (Hexagon::DoubleRegsRegClass.contains(Reg)) { | 
|  | 448 | for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) | 
|  | 449 | LastDef[*SubRegs] = &MI; | 
|  | 450 | } else if (Hexagon::IntRegsRegClass.contains(Reg)) | 
|  | 451 | LastDef[Reg] = &MI; | 
|  | 452 | } else if (Op.isRegMask()) { | 
|  | 453 | for (unsigned Reg : Hexagon::IntRegsRegClass) | 
|  | 454 | if (Op.clobbersPhysReg(Reg)) | 
|  | 455 | LastDef[Reg] = &MI; | 
|  | 456 | } | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 457 | } | 
|  | 458 | } | 
|  | 459 | } | 
|  | 460 |  | 
|  | 461 | bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) { | 
| Krzysztof Parzyszek | 643aaea | 2017-04-14 15:26:34 +0000 | [diff] [blame] | 462 | if (skipFunction(*MF.getFunction())) | 
|  | 463 | return false; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 464 |  | 
|  | 465 | if (IsCombinesDisabled) return false; | 
|  | 466 |  | 
|  | 467 | bool HasChanged = false; | 
|  | 468 |  | 
|  | 469 | // Get target info. | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 470 | ST = &MF.getSubtarget<HexagonSubtarget>(); | 
|  | 471 | TRI = ST->getRegisterInfo(); | 
|  | 472 | TII = ST->getInstrInfo(); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 473 |  | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 474 | const Function *F = MF.getFunction(); | 
|  | 475 | bool OptForSize = F->hasFnAttribute(Attribute::OptimizeForSize); | 
|  | 476 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 477 | // Combine aggressively (for code size) | 
|  | 478 | ShouldCombineAggressively = | 
|  | 479 | MF.getTarget().getOptLevel() <= CodeGenOpt::Default; | 
|  | 480 |  | 
|  | 481 | // Traverse basic blocks. | 
|  | 482 | for (MachineFunction::iterator BI = MF.begin(), BE = MF.end(); BI != BE; | 
|  | 483 | ++BI) { | 
|  | 484 | PotentiallyNewifiableTFR.clear(); | 
|  | 485 | findPotentialNewifiableTFRs(*BI); | 
|  | 486 |  | 
|  | 487 | // Traverse instructions in basic block. | 
|  | 488 | for(MachineBasicBlock::iterator MI = BI->begin(), End = BI->end(); | 
|  | 489 | MI != End;) { | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 490 | MachineInstr &I1 = *MI++; | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 491 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 492 | if (I1.isDebugValue()) | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 493 | continue; | 
|  | 494 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 495 | // Don't combine a TFR whose user could be newified (instructions that | 
|  | 496 | // define double registers can not be newified - Programmer's Ref Manual | 
|  | 497 | // 5.4.2 New-value stores). | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 498 | if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&I1)) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 499 | continue; | 
|  | 500 |  | 
|  | 501 | // Ignore instructions that are not combinable. | 
|  | 502 | if (!isCombinableInstType(I1, TII, ShouldCombineAggressively)) | 
|  | 503 | continue; | 
|  | 504 |  | 
|  | 505 | // Find a second instruction that can be merged into a combine | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 506 | // instruction. In addition, also find all the debug instructions that | 
|  | 507 | // need to be moved along with it. | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 508 | bool DoInsertAtI1 = false; | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 509 | DbgMItoMove.clear(); | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 510 | MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 511 | if (I2) { | 
|  | 512 | HasChanged = true; | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 513 | combine(I1, *I2, MI, DoInsertAtI1, OptForSize); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 514 | } | 
|  | 515 | } | 
|  | 516 | } | 
|  | 517 |  | 
|  | 518 | return HasChanged; | 
|  | 519 | } | 
|  | 520 |  | 
|  | 521 | /// findPairable - Returns an instruction that can be merged with \p I1 into a | 
|  | 522 | /// COMBINE instruction or 0 if no such instruction can be found. Returns true | 
|  | 523 | /// in \p DoInsertAtI1 if the combine must be inserted at instruction \p I1 | 
|  | 524 | /// false if the combine must be inserted at the returned instruction. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 525 | MachineInstr *HexagonCopyToCombine::findPairable(MachineInstr &I1, | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 526 | bool &DoInsertAtI1, | 
|  | 527 | bool AllowC64) { | 
| Benjamin Kramer | b6d0bd4 | 2014-03-02 12:27:27 +0000 | [diff] [blame] | 528 | MachineBasicBlock::iterator I2 = std::next(MachineBasicBlock::iterator(I1)); | 
| Krzysztof Parzyszek | 6dff336 | 2016-08-24 22:36:35 +0000 | [diff] [blame] | 529 | while (I2 != I1.getParent()->end() && I2->isDebugValue()) | 
|  | 530 | ++I2; | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 531 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 532 | unsigned I1DestReg = I1.getOperand(0).getReg(); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 533 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 534 | for (MachineBasicBlock::iterator End = I1.getParent()->end(); I2 != End; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 535 | ++I2) { | 
|  | 536 | // Bail out early if we see a second definition of I1DestReg. | 
|  | 537 | if (I2->modifiesRegister(I1DestReg, TRI)) | 
|  | 538 | break; | 
|  | 539 |  | 
|  | 540 | // Ignore non-combinable instructions. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 541 | if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively)) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 542 | continue; | 
|  | 543 |  | 
|  | 544 | // Don't combine a TFR whose user could be newified. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 545 | if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&*I2)) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 546 | continue; | 
|  | 547 |  | 
|  | 548 | unsigned I2DestReg = I2->getOperand(0).getReg(); | 
|  | 549 |  | 
|  | 550 | // Check that registers are adjacent and that the first destination register | 
|  | 551 | // is even. | 
|  | 552 | bool IsI1LowReg = (I2DestReg - I1DestReg) == 1; | 
|  | 553 | bool IsI2LowReg = (I1DestReg - I2DestReg) == 1; | 
|  | 554 | unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg; | 
|  | 555 | if ((!IsI1LowReg && !IsI2LowReg) || !isEvenReg(FirstRegIndex)) | 
|  | 556 | continue; | 
|  | 557 |  | 
|  | 558 | // Check that the two instructions are combinable. V4 allows more | 
|  | 559 | // instructions to be merged into a combine. | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 560 | // The order matters because in a A2_tfrsi we might can encode a int8 as | 
|  | 561 | // the hi reg operand but only a uint6 as the low reg operand. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 562 | if ((IsI2LowReg && !areCombinableOperations(TRI, I1, *I2, AllowC64)) || | 
|  | 563 | (IsI1LowReg && !areCombinableOperations(TRI, *I2, I1, AllowC64))) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 564 | break; | 
|  | 565 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 566 | if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1)) | 
|  | 567 | return &*I2; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 568 |  | 
|  | 569 | // Not safe. Stop searching. | 
|  | 570 | break; | 
|  | 571 | } | 
| Craig Topper | 062a2ba | 2014-04-25 05:30:21 +0000 | [diff] [blame] | 572 | return nullptr; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 573 | } | 
|  | 574 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 575 | void HexagonCopyToCombine::combine(MachineInstr &I1, MachineInstr &I2, | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 576 | MachineBasicBlock::iterator &MI, | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 577 | bool DoInsertAtI1, bool OptForSize) { | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 578 | // We are going to delete I2. If MI points to I2 advance it to the next | 
|  | 579 | // instruction. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 580 | if (MI == I2.getIterator()) | 
|  | 581 | ++MI; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 582 |  | 
|  | 583 | // Figure out whether I1 or I2 goes into the lowreg part. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 584 | unsigned I1DestReg = I1.getOperand(0).getReg(); | 
|  | 585 | unsigned I2DestReg = I2.getOperand(0).getReg(); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 586 | bool IsI1Loreg = (I2DestReg - I1DestReg) == 1; | 
|  | 587 | unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg; | 
| Krzysztof Parzyszek | a540997 | 2016-11-09 16:19:08 +0000 | [diff] [blame] | 588 | unsigned SubLo; | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 589 |  | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 590 | const TargetRegisterClass *SuperRC = nullptr; | 
|  | 591 | if (Hexagon::IntRegsRegClass.contains(LoRegDef)) { | 
|  | 592 | SuperRC = &Hexagon::DoubleRegsRegClass; | 
| Krzysztof Parzyszek | a540997 | 2016-11-09 16:19:08 +0000 | [diff] [blame] | 593 | SubLo = Hexagon::isub_lo; | 
| Krzysztof Parzyszek | 5577297 | 2017-09-15 15:46:05 +0000 | [diff] [blame] | 594 | } else if (Hexagon::HvxVRRegClass.contains(LoRegDef)) { | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 595 | assert(ST->useHVXOps()); | 
| Krzysztof Parzyszek | 5577297 | 2017-09-15 15:46:05 +0000 | [diff] [blame] | 596 | SuperRC = &Hexagon::HvxWRRegClass; | 
| Krzysztof Parzyszek | a540997 | 2016-11-09 16:19:08 +0000 | [diff] [blame] | 597 | SubLo = Hexagon::vsub_lo; | 
| Krzysztof Parzyszek | f817efb | 2016-11-09 17:50:46 +0000 | [diff] [blame] | 598 | } else | 
|  | 599 | llvm_unreachable("Unexpected register class"); | 
|  | 600 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 601 | // Get the double word register. | 
| Krzysztof Parzyszek | a540997 | 2016-11-09 16:19:08 +0000 | [diff] [blame] | 602 | unsigned DoubleRegDest = TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 603 | assert(DoubleRegDest != 0 && "Expect a valid register"); | 
|  | 604 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 605 | // Setup source operands. | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 606 | MachineOperand &LoOperand = IsI1Loreg ? I1.getOperand(1) : I2.getOperand(1); | 
|  | 607 | MachineOperand &HiOperand = IsI1Loreg ? I2.getOperand(1) : I1.getOperand(1); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 608 |  | 
|  | 609 | // Figure out which source is a register and which a constant. | 
|  | 610 | bool IsHiReg = HiOperand.isReg(); | 
|  | 611 | bool IsLoReg = LoOperand.isReg(); | 
|  | 612 |  | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 613 | // There is a combine of two constant extended values into CONST64. | 
|  | 614 | bool IsC64 = OptForSize && LoOperand.isImm() && HiOperand.isImm() && | 
|  | 615 | isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2); | 
|  | 616 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 617 | MachineBasicBlock::iterator InsertPt(DoInsertAtI1 ? I1 : I2); | 
|  | 618 | // Emit combine. | 
|  | 619 | if (IsHiReg && IsLoReg) | 
|  | 620 | emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand); | 
|  | 621 | else if (IsHiReg) | 
|  | 622 | emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand); | 
|  | 623 | else if (IsLoReg) | 
|  | 624 | emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand); | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 625 | else if (IsC64 && !IsConst64Disabled) | 
|  | 626 | emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 627 | else | 
|  | 628 | emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand); | 
|  | 629 |  | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 630 | // Move debug instructions along with I1 if it's being | 
|  | 631 | // moved towards I2. | 
|  | 632 | if (!DoInsertAtI1 && DbgMItoMove.size() != 0) { | 
|  | 633 | // Insert debug instructions at the new location before I2. | 
|  | 634 | MachineBasicBlock *BB = InsertPt->getParent(); | 
|  | 635 | for (auto NewMI : DbgMItoMove) { | 
|  | 636 | // If iterator MI is pointing to DEBUG_VAL, make sure | 
|  | 637 | // MI now points to next relevant instruction. | 
| Duncan P. N. Exon Smith | f197b1f | 2016-08-12 05:05:36 +0000 | [diff] [blame] | 638 | if (NewMI == MI) | 
| Krzysztof Parzyszek | 9b7320e | 2016-01-15 13:55:57 +0000 | [diff] [blame] | 639 | ++MI; | 
|  | 640 | BB->splice(InsertPt, BB, NewMI); | 
|  | 641 | } | 
|  | 642 | } | 
|  | 643 |  | 
| Duncan P. N. Exon Smith | 98226e3 | 2016-07-12 01:55:32 +0000 | [diff] [blame] | 644 | I1.eraseFromParent(); | 
|  | 645 | I2.eraseFromParent(); | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 646 | } | 
|  | 647 |  | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 648 | void HexagonCopyToCombine::emitConst64(MachineBasicBlock::iterator &InsertPt, | 
|  | 649 | unsigned DoubleDestReg, | 
|  | 650 | MachineOperand &HiOperand, | 
|  | 651 | MachineOperand &LoOperand) { | 
|  | 652 | DEBUG(dbgs() << "Found a CONST64\n"); | 
|  | 653 |  | 
|  | 654 | DebugLoc DL = InsertPt->getDebugLoc(); | 
|  | 655 | MachineBasicBlock *BB = InsertPt->getParent(); | 
|  | 656 | assert(LoOperand.isImm() && HiOperand.isImm() && | 
|  | 657 | "Both operands must be immediate"); | 
|  | 658 |  | 
|  | 659 | int64_t V = HiOperand.getImm(); | 
|  | 660 | V = (V << 32) | (0x0ffffffffLL & LoOperand.getImm()); | 
| Krzysztof Parzyszek | a338650 | 2016-08-10 16:46:36 +0000 | [diff] [blame] | 661 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::CONST64), DoubleDestReg) | 
| Krzysztof Parzyszek | 2a3b2f9 | 2016-01-15 14:08:31 +0000 | [diff] [blame] | 662 | .addImm(V); | 
|  | 663 | } | 
|  | 664 |  | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 665 | void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt, | 
|  | 666 | unsigned DoubleDestReg, | 
|  | 667 | MachineOperand &HiOperand, | 
|  | 668 | MachineOperand &LoOperand) { | 
|  | 669 | DebugLoc DL = InsertPt->getDebugLoc(); | 
|  | 670 | MachineBasicBlock *BB = InsertPt->getParent(); | 
|  | 671 |  | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 672 | // Handle globals. | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 673 | if (HiOperand.isGlobal()) { | 
| Colin LeMahieu | b580d7d | 2014-12-09 19:23:45 +0000 | [diff] [blame] | 674 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 675 | .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(), | 
|  | 676 | HiOperand.getTargetFlags()) | 
|  | 677 | .addImm(LoOperand.getImm()); | 
|  | 678 | return; | 
|  | 679 | } | 
|  | 680 | if (LoOperand.isGlobal()) { | 
| Colin LeMahieu | 82fb8cb | 2014-12-30 17:53:54 +0000 | [diff] [blame] | 681 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 682 | .addImm(HiOperand.getImm()) | 
|  | 683 | .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(), | 
|  | 684 | LoOperand.getTargetFlags()); | 
|  | 685 | return; | 
|  | 686 | } | 
|  | 687 |  | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 688 | // Handle block addresses. | 
|  | 689 | if (HiOperand.isBlockAddress()) { | 
| Colin LeMahieu | b580d7d | 2014-12-09 19:23:45 +0000 | [diff] [blame] | 690 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 691 | .addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(), | 
|  | 692 | HiOperand.getTargetFlags()) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 693 | .addImm(LoOperand.getImm()); | 
|  | 694 | return; | 
|  | 695 | } | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 696 | if (LoOperand.isBlockAddress()) { | 
|  | 697 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg) | 
|  | 698 | .addImm(HiOperand.getImm()) | 
|  | 699 | .addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(), | 
|  | 700 | LoOperand.getTargetFlags()); | 
|  | 701 | return; | 
|  | 702 | } | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 703 |  | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 704 | // Handle jump tables. | 
|  | 705 | if (HiOperand.isJTI()) { | 
|  | 706 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) | 
|  | 707 | .addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags()) | 
|  | 708 | .addImm(LoOperand.getImm()); | 
|  | 709 | return; | 
|  | 710 | } | 
|  | 711 | if (LoOperand.isJTI()) { | 
|  | 712 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg) | 
|  | 713 | .addImm(HiOperand.getImm()) | 
|  | 714 | .addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags()); | 
|  | 715 | return; | 
|  | 716 | } | 
|  | 717 |  | 
|  | 718 | // Handle constant pools. | 
|  | 719 | if (HiOperand.isCPI()) { | 
|  | 720 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) | 
|  | 721 | .addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(), | 
|  | 722 | HiOperand.getTargetFlags()) | 
|  | 723 | .addImm(LoOperand.getImm()); | 
|  | 724 | return; | 
|  | 725 | } | 
|  | 726 | if (LoOperand.isCPI()) { | 
|  | 727 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg) | 
|  | 728 | .addImm(HiOperand.getImm()) | 
|  | 729 | .addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(), | 
|  | 730 | LoOperand.getTargetFlags()); | 
|  | 731 | return; | 
|  | 732 | } | 
|  | 733 |  | 
|  | 734 | // First preference should be given to Hexagon::A2_combineii instruction | 
|  | 735 | // as it can include U6 (in Hexagon::A4_combineii) as well. | 
|  | 736 | // In this instruction, HiOperand is const extended, if required. | 
|  | 737 | if (isInt<8>(LoOperand.getImm())) { | 
|  | 738 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) | 
|  | 739 | .addImm(HiOperand.getImm()) | 
|  | 740 | .addImm(LoOperand.getImm()); | 
|  | 741 | return; | 
|  | 742 | } | 
|  | 743 |  | 
|  | 744 | // In this instruction, LoOperand is const extended, if required. | 
|  | 745 | if (isInt<8>(HiOperand.getImm())) { | 
| Colin LeMahieu | 82fb8cb | 2014-12-30 17:53:54 +0000 | [diff] [blame] | 746 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 747 | .addImm(HiOperand.getImm()) | 
|  | 748 | .addImm(LoOperand.getImm()); | 
|  | 749 | return; | 
|  | 750 | } | 
|  | 751 |  | 
|  | 752 | // Insert new combine instruction. | 
|  | 753 | //  DoubleRegDest = combine #HiImm, #LoImm | 
| Colin LeMahieu | b580d7d | 2014-12-09 19:23:45 +0000 | [diff] [blame] | 754 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 755 | .addImm(HiOperand.getImm()) | 
|  | 756 | .addImm(LoOperand.getImm()); | 
|  | 757 | } | 
|  | 758 |  | 
|  | 759 | void HexagonCopyToCombine::emitCombineIR(MachineBasicBlock::iterator &InsertPt, | 
|  | 760 | unsigned DoubleDestReg, | 
|  | 761 | MachineOperand &HiOperand, | 
|  | 762 | MachineOperand &LoOperand) { | 
|  | 763 | unsigned LoReg = LoOperand.getReg(); | 
|  | 764 | unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill()); | 
|  | 765 |  | 
|  | 766 | DebugLoc DL = InsertPt->getDebugLoc(); | 
|  | 767 | MachineBasicBlock *BB = InsertPt->getParent(); | 
|  | 768 |  | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 769 | // Handle globals. | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 770 | if (HiOperand.isGlobal()) { | 
| Colin LeMahieu | 82fb8cb | 2014-12-30 17:53:54 +0000 | [diff] [blame] | 771 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 772 | .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(), | 
|  | 773 | HiOperand.getTargetFlags()) | 
|  | 774 | .addReg(LoReg, LoRegKillFlag); | 
|  | 775 | return; | 
|  | 776 | } | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 777 | // Handle block addresses. | 
|  | 778 | if (HiOperand.isBlockAddress()) { | 
|  | 779 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg) | 
|  | 780 | .addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(), | 
|  | 781 | HiOperand.getTargetFlags()) | 
|  | 782 | .addReg(LoReg, LoRegKillFlag); | 
|  | 783 | return; | 
|  | 784 | } | 
|  | 785 | // Handle jump tables. | 
|  | 786 | if (HiOperand.isJTI()) { | 
|  | 787 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg) | 
|  | 788 | .addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags()) | 
|  | 789 | .addReg(LoReg, LoRegKillFlag); | 
|  | 790 | return; | 
|  | 791 | } | 
|  | 792 | // Handle constant pools. | 
|  | 793 | if (HiOperand.isCPI()) { | 
|  | 794 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg) | 
|  | 795 | .addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(), | 
|  | 796 | HiOperand.getTargetFlags()) | 
|  | 797 | .addReg(LoReg, LoRegKillFlag); | 
|  | 798 | return; | 
|  | 799 | } | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 800 | // Insert new combine instruction. | 
|  | 801 | //  DoubleRegDest = combine #HiImm, LoReg | 
| Colin LeMahieu | 82fb8cb | 2014-12-30 17:53:54 +0000 | [diff] [blame] | 802 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 803 | .addImm(HiOperand.getImm()) | 
|  | 804 | .addReg(LoReg, LoRegKillFlag); | 
|  | 805 | } | 
|  | 806 |  | 
|  | 807 | void HexagonCopyToCombine::emitCombineRI(MachineBasicBlock::iterator &InsertPt, | 
|  | 808 | unsigned DoubleDestReg, | 
|  | 809 | MachineOperand &HiOperand, | 
|  | 810 | MachineOperand &LoOperand) { | 
|  | 811 | unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill()); | 
|  | 812 | unsigned HiReg = HiOperand.getReg(); | 
|  | 813 |  | 
|  | 814 | DebugLoc DL = InsertPt->getDebugLoc(); | 
|  | 815 | MachineBasicBlock *BB = InsertPt->getParent(); | 
|  | 816 |  | 
|  | 817 | // Handle global. | 
|  | 818 | if (LoOperand.isGlobal()) { | 
| Colin LeMahieu | 82fb8cb | 2014-12-30 17:53:54 +0000 | [diff] [blame] | 819 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 820 | .addReg(HiReg, HiRegKillFlag) | 
|  | 821 | .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(), | 
|  | 822 | LoOperand.getTargetFlags()); | 
|  | 823 | return; | 
|  | 824 | } | 
| Krzysztof Parzyszek | cd97c98 | 2015-04-22 18:25:53 +0000 | [diff] [blame] | 825 | // Handle block addresses. | 
|  | 826 | if (LoOperand.isBlockAddress()) { | 
|  | 827 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg) | 
|  | 828 | .addReg(HiReg, HiRegKillFlag) | 
|  | 829 | .addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(), | 
|  | 830 | LoOperand.getTargetFlags()); | 
|  | 831 | return; | 
|  | 832 | } | 
|  | 833 | // Handle jump tables. | 
|  | 834 | if (LoOperand.isJTI()) { | 
|  | 835 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg) | 
|  | 836 | .addReg(HiOperand.getReg(), HiRegKillFlag) | 
|  | 837 | .addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags()); | 
|  | 838 | return; | 
|  | 839 | } | 
|  | 840 | // Handle constant pools. | 
|  | 841 | if (LoOperand.isCPI()) { | 
|  | 842 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg) | 
|  | 843 | .addReg(HiOperand.getReg(), HiRegKillFlag) | 
|  | 844 | .addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(), | 
|  | 845 | LoOperand.getTargetFlags()); | 
|  | 846 | return; | 
|  | 847 | } | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 848 |  | 
|  | 849 | // Insert new combine instruction. | 
|  | 850 | //  DoubleRegDest = combine HiReg, #LoImm | 
| Colin LeMahieu | 82fb8cb | 2014-12-30 17:53:54 +0000 | [diff] [blame] | 851 | BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 852 | .addReg(HiReg, HiRegKillFlag) | 
|  | 853 | .addImm(LoOperand.getImm()); | 
|  | 854 | } | 
|  | 855 |  | 
|  | 856 | void HexagonCopyToCombine::emitCombineRR(MachineBasicBlock::iterator &InsertPt, | 
|  | 857 | unsigned DoubleDestReg, | 
|  | 858 | MachineOperand &HiOperand, | 
|  | 859 | MachineOperand &LoOperand) { | 
|  | 860 | unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill()); | 
|  | 861 | unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill()); | 
|  | 862 | unsigned LoReg = LoOperand.getReg(); | 
|  | 863 | unsigned HiReg = HiOperand.getReg(); | 
|  | 864 |  | 
|  | 865 | DebugLoc DL = InsertPt->getDebugLoc(); | 
|  | 866 | MachineBasicBlock *BB = InsertPt->getParent(); | 
|  | 867 |  | 
|  | 868 | // Insert new combine instruction. | 
|  | 869 | //  DoubleRegDest = combine HiReg, LoReg | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 870 | unsigned NewOpc; | 
|  | 871 | if (Hexagon::DoubleRegsRegClass.contains(DoubleDestReg)) { | 
|  | 872 | NewOpc = Hexagon::A2_combinew; | 
| Krzysztof Parzyszek | 5577297 | 2017-09-15 15:46:05 +0000 | [diff] [blame] | 873 | } else if (Hexagon::HvxWRRegClass.contains(DoubleDestReg)) { | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 874 | assert(ST->useHVXOps()); | 
| Krzysztof Parzyszek | 5577297 | 2017-09-15 15:46:05 +0000 | [diff] [blame] | 875 | NewOpc = Hexagon::V6_vcombine; | 
| Krzysztof Parzyszek | b1b0372 | 2016-08-18 14:12:34 +0000 | [diff] [blame] | 876 | } else | 
|  | 877 | llvm_unreachable("Unexpected register"); | 
|  | 878 |  | 
|  | 879 | BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg) | 
| Jyotsna Verma | 803e506 | 2013-05-14 18:54:06 +0000 | [diff] [blame] | 880 | .addReg(HiReg, HiRegKillFlag) | 
|  | 881 | .addReg(LoReg, LoRegKillFlag); | 
|  | 882 | } | 
|  | 883 |  | 
|  | 884 | FunctionPass *llvm::createHexagonCopyToCombine() { | 
|  | 885 | return new HexagonCopyToCombine(); | 
|  | 886 | } |