Index: include/llvm/Target/TargetInstrInfo.h =================================================================== --- include/llvm/Target/TargetInstrInfo.h +++ include/llvm/Target/TargetInstrInfo.h @@ -1136,6 +1136,15 @@ return false; } + /// Check if the given operand has a compile-time known constant + /// value. Return true if yes, and false otherwise. When returning true, set + /// Val to the corresponding constant value. + virtual bool getInstrOperandImmValue(const MachineInstr &MI, + const MachineOperand &MO, + int64_t &Val) const { + return false; + } + /// If the specified instruction defines any predicate /// or condition code register(s) used for predication, returns true as well /// as the definition predicate(s) by reference. Index: lib/Target/Hexagon/HexagonHardwareLoops.cpp =================================================================== --- lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -232,21 +232,18 @@ MachineBasicBlock *MBB, MachineLoop *L, LoopFeederMap &LoopFeederPhi) const; - /// \brief Check if the given operand has a compile-time known constant - /// value. Return true if yes, and false otherwise. When returning true, set - /// Val to the corresponding constant value. - bool checkForImmediate(const MachineOperand &MO, int64_t &Val) const; - /// \brief Check if the operand has a compile-time known constant value. - bool isImmediate(const MachineOperand &MO) const { + bool isImmediate(const HexagonInstrInfo *TII, + const MachineOperand &MO) const { int64_t V; - return checkForImmediate(MO, V); + return TII->getInstrOperandImmValue(*MO.getParent(), MO, V); } /// \brief Return the immediate for the specified operand. - int64_t getImmediate(const MachineOperand &MO) const { + int64_t getImmediate(const HexagonInstrInfo *TII, + const MachineOperand &MO) const { int64_t V; - if (!checkForImmediate(MO, V)) + if (!TII->getInstrOperandImmValue(*MO.getParent(), MO, V)) llvm_unreachable("Invalid operand"); return V; } @@ -418,7 +415,8 @@ unsigned IndReg = DI->getOperand(1).getReg(); MachineOperand &Opnd2 = DI->getOperand(2); int64_t V; - if (MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) { + if (MRI->getVRegDef(IndReg) == Phi && + TII->getInstrOperandImmValue(*DI, Opnd2, V)) { unsigned UpdReg = DI->getOperand(0).getReg(); IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V))); } @@ -1380,7 +1378,7 @@ // A register value that is assigned an immediate is a known value, and it // won't underflow in the first iteration. int64_t Imm; - if (checkForImmediate(*InitVal, Imm)) + if (TII->getInstrOperandImmValue(*InitVal->getParent(), *InitVal, Imm)) return (EndVal->getImm() == Imm); unsigned Reg = InitVal->getReg(); @@ -1448,88 +1446,6 @@ return true; } -bool HexagonHardwareLoops::checkForImmediate(const MachineOperand &MO, - int64_t &Val) const { - if (MO.isImm()) { - Val = MO.getImm(); - return true; - } - if (!MO.isReg()) - return false; - - // MO is a register. Check whether it is defined as an immediate value, - // and if so, get the value of it in TV. That value will then need to be - // processed to handle potential subregisters in MO. - int64_t TV; - - unsigned R = MO.getReg(); - if (!TargetRegisterInfo::isVirtualRegister(R)) - return false; - MachineInstr *DI = MRI->getVRegDef(R); - unsigned DOpc = DI->getOpcode(); - switch (DOpc) { - case TargetOpcode::COPY: - case Hexagon::A2_tfrsi: - case Hexagon::A2_tfrpi: - case Hexagon::CONST32: - case Hexagon::CONST64: { - // Call recursively to avoid an extra check whether operand(1) is - // indeed an immediate (it could be a global address, for example), - // plus we can handle COPY at the same time. - if (!checkForImmediate(DI->getOperand(1), TV)) - return false; - break; - } - case Hexagon::A2_combineii: - case Hexagon::A4_combineir: - case Hexagon::A4_combineii: - case Hexagon::A4_combineri: - case Hexagon::A2_combinew: { - const MachineOperand &S1 = DI->getOperand(1); - const MachineOperand &S2 = DI->getOperand(2); - int64_t V1, V2; - if (!checkForImmediate(S1, V1) || !checkForImmediate(S2, V2)) - return false; - TV = V2 | (V1 << 32); - break; - } - case TargetOpcode::REG_SEQUENCE: { - const MachineOperand &S1 = DI->getOperand(1); - const MachineOperand &S3 = DI->getOperand(3); - int64_t V1, V3; - if (!checkForImmediate(S1, V1) || !checkForImmediate(S3, V3)) - return false; - unsigned Sub2 = DI->getOperand(2).getImm(); - unsigned Sub4 = DI->getOperand(4).getImm(); - if (Sub2 == Hexagon::isub_lo && Sub4 == Hexagon::isub_hi) - TV = V1 | (V3 << 32); - else if (Sub2 == Hexagon::isub_hi && Sub4 == Hexagon::isub_lo) - TV = V3 | (V1 << 32); - else - llvm_unreachable("Unexpected form of REG_SEQUENCE"); - break; - } - - default: - return false; - } - - // By now, we should have successfully obtained the immediate value defining - // the register referenced in MO. Handle a potential use of a subregister. - switch (MO.getSubReg()) { - case Hexagon::isub_lo: - Val = TV & 0xFFFFFFFFULL; - break; - case Hexagon::isub_hi: - Val = (TV >> 32) & 0xFFFFFFFFULL; - break; - default: - Val = TV; - break; - } - return true; -} - void HexagonHardwareLoops::setImmediate(MachineOperand &MO, int64_t Val) { if (MO.isImm()) { MO.setImm(Val); @@ -1597,7 +1513,8 @@ unsigned IndReg = DI->getOperand(1).getReg(); MachineOperand &Opnd2 = DI->getOperand(2); int64_t V; - if (MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) { + if (MRI->getVRegDef(IndReg) == Phi && + TII->getInstrOperandImmValue(*DI, Opnd2, V)) { unsigned UpdReg = DI->getOperand(0).getReg(); IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V))); } @@ -1677,7 +1594,7 @@ if (MO.isImplicit()) continue; if (MO.isUse()) { - if (!isImmediate(MO)) { + if (!isImmediate(TII, MO)) { CmpRegs.insert(MO.getReg()); continue; } @@ -1761,7 +1678,7 @@ // If the register is being compared against an immediate, try changing // the compare instruction to use induction register and adjust the // immediate operand. - int64_t CmpImm = getImmediate(*CmpImmOp); + int64_t CmpImm = getImmediate(TII, *CmpImmOp); int64_t V = RB.second; // Handle Overflow (64-bit). if (((V > 0) && (CmpImm > INT64_MAX - V)) || Index: lib/Target/Hexagon/HexagonInstrInfo.h =================================================================== --- lib/Target/Hexagon/HexagonInstrInfo.h +++ lib/Target/Hexagon/HexagonInstrInfo.h @@ -284,6 +284,12 @@ bool isTailCall(const MachineInstr &MI) const override; + /// Check if the given operand has a compile-time known constant + /// value. Return true if yes, and false otherwise. When returning true, set + /// Val to the corresponding constant value. + bool getInstrOperandImmValue(const MachineInstr &MI, const MachineOperand &MO, + int64_t &Val) const override; + /// HexagonInstrInfo specifics. /// Index: lib/Target/Hexagon/HexagonInstrInfo.cpp =================================================================== --- lib/Target/Hexagon/HexagonInstrInfo.cpp +++ lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -2525,6 +2525,98 @@ } +bool +HexagonInstrInfo::getInstrOperandImmValue(const MachineInstr &MI, + const MachineOperand &MO, + int64_t &Val) const { + const MachineFunction *MF = MI.getParent()->getParent(); + const MachineRegisterInfo *MRI = &MF->getRegInfo(); + + if (MO.isImm()) { + Val = MO.getImm(); + return true; + } + + if (!MO.isReg()) + return false; + + // MO is a register. Check whether it is defined as an immediate value, + // and if so, get the value of it in TV. That value will then need to be + // processed to handle potential subregisters in MO. + int64_t TV; + + unsigned R = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(R)) + return false; + + MachineInstr *DI = MRI->getVRegDef(R); + unsigned DOpc = DI->getOpcode(); + + switch (DOpc) { + case TargetOpcode::COPY: + case Hexagon::A2_tfrsi: + case Hexagon::A2_tfrpi: + case Hexagon::CONST32: + case Hexagon::CONST64: { + // Call recursively to avoid an extra check whether operand(1) is + // indeed an immediate (it could be a global address, for example), + // plus we can handle COPY at the same time. + if (!getInstrOperandImmValue(MI, DI->getOperand(1), TV)) + return false; + break; + } + case Hexagon::A2_combineii: + case Hexagon::A4_combineir: + case Hexagon::A4_combineii: + case Hexagon::A4_combineri: + case Hexagon::A2_combinew: { + const MachineOperand &S1 = DI->getOperand(1); + const MachineOperand &S2 = DI->getOperand(2); + int64_t V1, V2; + if (!getInstrOperandImmValue(MI, S1, V1) || !getInstrOperandImmValue(MI, S2, V2)) + return false; + TV = V2 | (V1 << 32); + break; + } + case TargetOpcode::REG_SEQUENCE: { + const MachineOperand &S1 = DI->getOperand(1); + const MachineOperand &S3 = DI->getOperand(3); + int64_t V1, V3; + if (!getInstrOperandImmValue(MI, S1, V1) || !getInstrOperandImmValue(MI, S3, V3)) + return false; + int64_t Sub2 = DI->getOperand(2).getImm(); + int64_t Sub4 = DI->getOperand(4).getImm(); + if (Sub2 == Hexagon::subreg_loreg && Sub4 == Hexagon::subreg_hireg) + TV = V1 | (V3 << 32); + else if (Sub2 == Hexagon::subreg_hireg && Sub4 == Hexagon::subreg_loreg) + TV = V3 | (V1 << 32); + else + llvm_unreachable("Unexpected form of REG_SEQUENCE"); + break; + } + + default: + return false; + } + + // By now, we should have successfuly obtained the immediate value defining + // the register referenced in MO. Handle a potential use of a subregister. + switch (MO.getSubReg()) { + case Hexagon::subreg_loreg: + Val = TV & 0xFFFFFFFFULL; + break; + case Hexagon::subreg_hireg: + Val = (TV >> 32) & 0xFFFFFFFFULL; + break; + default: + Val = TV; + break; + } + + return true; +} + + // Returns true when SU has a timing class TC1. bool HexagonInstrInfo::isTC1(const MachineInstr &MI) const { unsigned SchedClass = MI.getDesc().getSchedClass();