diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-08-02 17:32:43 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-08-02 17:32:43 +0000 |
commit | b7eb8e35e481a74962664b63dfb09483b200209a (patch) | |
tree | 1937fb4a348458ce2d02ade03ac3bb0aa18d2fcd /lib/Target/Hexagon | |
parent | eb11fae6d08f479c0799db45860a98af528fa6e7 (diff) |
Diffstat (limited to 'lib/Target/Hexagon')
-rw-r--r-- | lib/Target/Hexagon/HexagonBitSimplify.cpp | 123 | ||||
-rw-r--r-- | lib/Target/Hexagon/HexagonBitTracker.cpp | 36 | ||||
-rw-r--r-- | lib/Target/Hexagon/HexagonBitTracker.h | 1 |
3 files changed, 157 insertions, 3 deletions
diff --git a/lib/Target/Hexagon/HexagonBitSimplify.cpp b/lib/Target/Hexagon/HexagonBitSimplify.cpp index 4791b067aa8d..ba255d30fede 100644 --- a/lib/Target/Hexagon/HexagonBitSimplify.cpp +++ b/lib/Target/Hexagon/HexagonBitSimplify.cpp @@ -1777,6 +1777,7 @@ namespace { const BitTracker::RegisterCell &RC); bool simplifyExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC, const RegisterSet &AVs); + bool simplifyRCmp0(MachineInstr *MI, BitTracker::RegisterRef RD); // Cache of created instructions to avoid creating duplicates. // XXX Currently only used by genBitSplit. @@ -2567,6 +2568,127 @@ bool BitSimplification::simplifyExtractLow(MachineInstr *MI, return Changed; } +bool BitSimplification::simplifyRCmp0(MachineInstr *MI, + BitTracker::RegisterRef RD) { + unsigned Opc = MI->getOpcode(); + if (Opc != Hexagon::A4_rcmpeqi && Opc != Hexagon::A4_rcmpneqi) + return false; + MachineOperand &CmpOp = MI->getOperand(2); + if (!CmpOp.isImm() || CmpOp.getImm() != 0) + return false; + + const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI); + if (FRC != &Hexagon::IntRegsRegClass && FRC != &Hexagon::DoubleRegsRegClass) + return false; + assert(RD.Sub == 0); + + MachineBasicBlock &B = *MI->getParent(); + const DebugLoc &DL = MI->getDebugLoc(); + auto At = MI->isPHI() ? B.getFirstNonPHI() + : MachineBasicBlock::iterator(MI); + bool KnownZ = true; + bool KnownNZ = false; + + BitTracker::RegisterRef SR = MI->getOperand(1); + if (!BT.has(SR.Reg)) + return false; + const BitTracker::RegisterCell &SC = BT.lookup(SR.Reg); + unsigned F, W; + if (!HBS::getSubregMask(SR, F, W, MRI)) + return false; + + for (uint16_t I = F; I != F+W; ++I) { + const BitTracker::BitValue &V = SC[I]; + if (!V.is(0)) + KnownZ = false; + if (V.is(1)) + KnownNZ = true; + } + + auto ReplaceWithConst = [&] (int C) { + unsigned NewR = MRI.createVirtualRegister(FRC); + BuildMI(B, At, DL, HII.get(Hexagon::A2_tfrsi), NewR) + .addImm(C); + HBS::replaceReg(RD.Reg, NewR, MRI); + BitTracker::RegisterCell NewRC(W); + for (uint16_t I = 0; I != W; ++I) { + NewRC[I] = BitTracker::BitValue(C & 1); + C = unsigned(C) >> 1; + } + BT.put(BitTracker::RegisterRef(NewR), NewRC); + return true; + }; + + auto IsNonZero = [] (const MachineOperand &Op) { + if (Op.isGlobal() || Op.isBlockAddress()) + return true; + if (Op.isImm()) + return Op.getImm() != 0; + if (Op.isCImm()) + return !Op.getCImm()->isZero(); + if (Op.isFPImm()) + return !Op.getFPImm()->isZero(); + return false; + }; + + auto IsZero = [] (const MachineOperand &Op) { + if (Op.isGlobal() || Op.isBlockAddress()) + return false; + if (Op.isImm()) + return Op.getImm() == 0; + if (Op.isCImm()) + return Op.getCImm()->isZero(); + if (Op.isFPImm()) + return Op.getFPImm()->isZero(); + return false; + }; + + // If the source register is known to be 0 or non-0, the comparison can + // be folded to a load of a constant. + if (KnownZ || KnownNZ) { + assert(KnownZ != KnownNZ && "Register cannot be both 0 and non-0"); + return ReplaceWithConst(KnownZ == (Opc == Hexagon::A4_rcmpeqi)); + } + + // Special case: if the compare comes from a C2_muxii, then we know the + // two possible constants that can be the source value. + MachineInstr *InpDef = MRI.getVRegDef(SR.Reg); + if (!InpDef) + return false; + if (SR.Sub == 0 && InpDef->getOpcode() == Hexagon::C2_muxii) { + MachineOperand &Src1 = InpDef->getOperand(2); + MachineOperand &Src2 = InpDef->getOperand(3); + // Check if both are non-zero. + bool KnownNZ1 = IsNonZero(Src1), KnownNZ2 = IsNonZero(Src2); + if (KnownNZ1 && KnownNZ2) + return ReplaceWithConst(Opc == Hexagon::A4_rcmpneqi); + // Check if both are zero. + bool KnownZ1 = IsZero(Src1), KnownZ2 = IsZero(Src2); + if (KnownZ1 && KnownZ2) + return ReplaceWithConst(Opc == Hexagon::A4_rcmpeqi); + + // If for both operands we know that they are either 0 or non-0, + // replace the comparison with a C2_muxii, using the same predicate + // register, but with operands substituted with 0/1 accordingly. + if ((KnownZ1 || KnownNZ1) && (KnownZ2 || KnownNZ2)) { + unsigned NewR = MRI.createVirtualRegister(FRC); + BuildMI(B, At, DL, HII.get(Hexagon::C2_muxii), NewR) + .addReg(InpDef->getOperand(1).getReg()) + .addImm(KnownZ1 == (Opc == Hexagon::A4_rcmpeqi)) + .addImm(KnownZ2 == (Opc == Hexagon::A4_rcmpeqi)); + HBS::replaceReg(RD.Reg, NewR, MRI); + // Create a new cell with only the least significant bit unknown. + BitTracker::RegisterCell NewRC(W); + NewRC[0] = BitTracker::BitValue::self(); + NewRC.fill(1, W, BitTracker::BitValue::Zero); + BT.put(BitTracker::RegisterRef(NewR), NewRC); + return true; + } + } + + return false; +} + bool BitSimplification::processBlock(MachineBasicBlock &B, const RegisterSet &AVs) { if (!BT.reached(&B)) @@ -2615,6 +2737,7 @@ bool BitSimplification::processBlock(MachineBasicBlock &B, T = T || genExtractHalf(MI, RD, RC); T = T || genCombineHalf(MI, RD, RC); T = T || genExtractLow(MI, RD, RC); + T = T || simplifyRCmp0(MI, RD); Changed |= T; continue; } diff --git a/lib/Target/Hexagon/HexagonBitTracker.cpp b/lib/Target/Hexagon/HexagonBitTracker.cpp index e13cfd3f655a..94aacbed6af6 100644 --- a/lib/Target/Hexagon/HexagonBitTracker.cpp +++ b/lib/Target/Hexagon/HexagonBitTracker.cpp @@ -347,9 +347,11 @@ bool HexagonEvaluator::evaluate(const MachineInstr &MI, return rr0(RC, Outputs); } case C2_tfrrp: { - RegisterCell RC = RegisterCell::self(Reg[0].Reg, W0); - W0 = 8; // XXX Pred size - return rr0(eINS(RC, eXTR(rc(1), 0, W0), 0), Outputs); + uint16_t RW = W0; + uint16_t PW = 8; // XXX Pred size: getRegBitWidth(Reg[1]); + RegisterCell RC = RegisterCell::self(Reg[0].Reg, RW); + RC.fill(PW, RW, BT::BitValue::Zero); + return rr0(eINS(RC, eXTR(rc(1), 0, PW), 0), Outputs); } // Arithmetic: @@ -950,6 +952,19 @@ bool HexagonEvaluator::evaluate(const MachineInstr &MI, } default: + // For instructions that define a single predicate registers, store + // the low 8 bits of the register only. + if (unsigned DefR = getUniqueDefVReg(MI)) { + if (MRI.getRegClass(DefR) == &Hexagon::PredRegsRegClass) { + BT::RegisterRef PD(DefR, 0); + uint16_t RW = getRegBitWidth(PD); + uint16_t PW = 8; // XXX Pred size: getRegBitWidth(Reg[1]); + RegisterCell RC = RegisterCell::self(DefR, RW); + RC.fill(PW, RW, BT::BitValue::Zero); + putCell(PD, RC, Outputs); + return true; + } + } return MachineEvaluator::evaluate(MI, Inputs, Outputs); } #undef im @@ -1016,6 +1031,21 @@ bool HexagonEvaluator::evaluate(const MachineInstr &BI, return true; } +unsigned HexagonEvaluator::getUniqueDefVReg(const MachineInstr &MI) const { + unsigned DefReg = 0; + for (const MachineOperand &Op : MI.operands()) { + if (!Op.isReg() || !Op.isDef()) + continue; + unsigned R = Op.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(R)) + continue; + if (DefReg != 0) + return 0; + DefReg = R; + } + return DefReg; +} + bool HexagonEvaluator::evaluateLoad(const MachineInstr &MI, const CellMapType &Inputs, CellMapType &Outputs) const { diff --git a/lib/Target/Hexagon/HexagonBitTracker.h b/lib/Target/Hexagon/HexagonBitTracker.h index d9dd04e1b088..f0b7c9d91950 100644 --- a/lib/Target/Hexagon/HexagonBitTracker.h +++ b/lib/Target/Hexagon/HexagonBitTracker.h @@ -49,6 +49,7 @@ struct HexagonEvaluator : public BitTracker::MachineEvaluator { const HexagonInstrInfo &TII; private: + unsigned getUniqueDefVReg(const MachineInstr &MI) const; bool evaluateLoad(const MachineInstr &MI, const CellMapType &Inputs, CellMapType &Outputs) const; bool evaluateFormalCopy(const MachineInstr &MI, const CellMapType &Inputs, |