// This is by no means complete
class BitSimplification : public Transformation {
public:
- BitSimplification(BitTracker &bt, const HexagonInstrInfo &hii,
- const HexagonRegisterInfo &hri, MachineRegisterInfo &mri,
- MachineFunction &mf)
- : Transformation(true), HII(hii), HRI(hri), MRI(mri), MF(mf), BT(bt) {}
+ BitSimplification(BitTracker &bt, const MachineDominatorTree &mdt,
+ const HexagonInstrInfo &hii, const HexagonRegisterInfo &hri,
+ MachineRegisterInfo &mri, MachineFunction &mf)
+ : Transformation(true), MDT(mdt), HII(hii), HRI(hri), MRI(mri),
+ MF(mf), BT(bt) {}
bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
bool simplifyExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD,
const BitTracker::RegisterCell &RC, const RegisterSet &AVs);
+ // Cache of created instructions to avoid creating duplicates.
+ // XXX Currently only used by genBitSplit.
+ std::vector<MachineInstr*> NewMIs;
+
+ const MachineDominatorTree &MDT;
const HexagonInstrInfo &HII;
const HexagonRegisterInfo &HRI;
MachineRegisterInfo &MRI;
assert(DefS != nullptr);
DebugLoc DL = DefS->getDebugLoc();
MachineBasicBlock &B = *DefS->getParent();
- auto At = MI->isPHI() ? B.getFirstNonPHI()
- : MachineBasicBlock::iterator(DefS);
+ auto At = DefS->isPHI() ? B.getFirstNonPHI()
+ : MachineBasicBlock::iterator(DefS);
if (MRI.getRegClass(SrcR)->getID() == Hexagon::DoubleRegsRegClassID)
SrcSR = (std::min(Pos, P) == 32) ? Hexagon::isub_hi : Hexagon::isub_lo;
- unsigned NewR = MRI.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
- BuildMI(B, At, DL, HII.get(Hexagon::A4_bitspliti), NewR)
- .addReg(SrcR, 0, SrcSR)
- .addImm(Pos <= P ? W-Z : Z);
+ if (!validateReg({SrcR,SrcSR}, Hexagon::A4_bitspliti, 1))
+ continue;
+ unsigned ImmOp = Pos <= P ? W-Z : Z;
+
+ // Find an existing bitsplit instruction if one already exists.
+ unsigned NewR = 0;
+ for (MachineInstr *In : NewMIs) {
+ if (In->getOpcode() != Hexagon::A4_bitspliti)
+ continue;
+ MachineOperand &Op1 = In->getOperand(1);
+ if (Op1.getReg() != SrcR || Op1.getSubReg() != SrcSR)
+ continue;
+ if (In->getOperand(2).getImm() != ImmOp)
+ continue;
+ // Check if the target register is available here.
+ MachineOperand &Op0 = In->getOperand(0);
+ MachineInstr *DefI = MRI.getVRegDef(Op0.getReg());
+ assert(DefI != nullptr);
+ if (!MDT.dominates(DefI, &*At))
+ continue;
+
+ // Found one that can be reused.
+ assert(Op0.getSubReg() == 0);
+ NewR = Op0.getReg();
+ break;
+ }
+ if (!NewR) {
+ NewR = MRI.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
+ auto NewBS = BuildMI(B, At, DL, HII.get(Hexagon::A4_bitspliti), NewR)
+ .addReg(SrcR, 0, SrcSR)
+ .addImm(ImmOp);
+ NewMIs.push_back(NewBS);
+ }
if (Pos <= P) {
HBS::replaceRegWithSub(RD.Reg, NewR, Hexagon::isub_lo, MRI);
HBS::replaceRegWithSub(S, NewR, Hexagon::isub_hi, MRI);
BT.run();
RegisterSet ABS; // Available registers for BS.
- BitSimplification BitS(BT, HII, HRI, MRI, MF);
+ BitSimplification BitS(BT, *MDT, HII, HRI, MRI, MF);
Changed |= visitBlock(Entry, BitS, ABS);
Changed = DeadCodeElimination(MF, *MDT).run() || Changed;
--- /dev/null
+; RUN: llc -march=hexagon < %s | FileCheck %s
+; REQUIRES: asserts
+
+; This testcase used to crash due to putting the bitsplit instruction in a
+; wrong place.
+; CHECK: bitsplit
+
+target triple = "hexagon"
+
+define hidden fastcc i32 @fred(i32 %a0) unnamed_addr #0 {
+b1:
+ %v2 = lshr i32 %a0, 16
+ %v3 = trunc i32 %v2 to i8
+ br i1 undef, label %b6, label %b4
+
+b4: ; preds = %b1
+ %v5 = and i32 %a0, 65535
+ br i1 undef, label %b8, label %b9
+
+b6: ; preds = %b1
+ %v7 = and i32 %a0, 65535
+ br label %b9
+
+b8: ; preds = %b4
+ store i8 %v3, i8* undef, align 2
+ unreachable
+
+b9: ; preds = %b6, %b4
+ %v10 = phi i32 [ %v7, %b6 ], [ %v5, %b4 ]
+ ret i32 %v10
+}
+
+attributes #0 = { nounwind optsize "target-cpu"="hexagonv60" "target-features"="-hvx-double,-long-calls" }