[llvm] r297239 - [Hexagon] Generate bitsplit instruction

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 7 15:08:35 PST 2017


Author: kparzysz
Date: Tue Mar  7 17:08:35 2017
New Revision: 297239

URL: http://llvm.org/viewvc/llvm-project?rev=297239&view=rev
Log:
[Hexagon] Generate bitsplit instruction

Added:
    llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit-src.ll
    llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit.ll
Modified:
    llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp

Modified: llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp?rev=297239&r1=297238&r2=297239&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp Tue Mar  7 17:08:35 2017
@@ -48,10 +48,15 @@ static cl::opt<bool> PreserveTiedOps("he
   cl::init(true), cl::desc("Preserve subregisters in tied operands"));
 static cl::opt<bool> GenExtract("hexbit-extract", cl::Hidden,
   cl::init(true), cl::desc("Generate extract instructions"));
+static cl::opt<bool> GenBitSplit("hexbit-bitsplit", cl::Hidden,
+  cl::init(true), cl::desc("Generate bitsplit instructions"));
 
 static cl::opt<unsigned> MaxExtract("hexbit-max-extract", cl::Hidden,
   cl::init(UINT_MAX));
 static unsigned CountExtract = 0;
+static cl::opt<unsigned> MaxBitSplit("hexbit-max-bitsplit", cl::Hidden,
+  cl::init(UINT_MAX));
+static unsigned CountBitSplit = 0;
 
 namespace llvm {
 
@@ -1769,6 +1774,8 @@ namespace {
           const BitTracker::RegisterCell &RC);
     bool genExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD,
           const BitTracker::RegisterCell &RC);
+    bool genBitSplit(MachineInstr *MI, BitTracker::RegisterRef RD,
+          const BitTracker::RegisterCell &RC, const RegisterSet &AVs);
     bool simplifyTstbit(MachineInstr *MI, BitTracker::RegisterRef RD,
           const BitTracker::RegisterCell &RC);
     bool simplifyExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD,
@@ -2155,6 +2162,115 @@ bool BitSimplification::genExtractLow(Ma
   return false;
 }
 
+bool BitSimplification::genBitSplit(MachineInstr *MI,
+      BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC,
+      const RegisterSet &AVs) {
+  if (!GenBitSplit)
+    return false;
+  if (CountBitSplit >= MaxBitSplit)
+    return false;
+
+  unsigned Opc = MI->getOpcode();
+  switch (Opc) {
+    case Hexagon::A4_bitsplit:
+    case Hexagon::A4_bitspliti:
+      return false;
+  }
+
+  unsigned W = RC.width();
+  if (W != 32)
+    return false;
+
+  auto ctlz = [] (const BitTracker::RegisterCell &C) -> unsigned {
+    unsigned Z = C.width();
+    while (Z > 0 && C[Z-1].is(0))
+      --Z;
+    return C.width() - Z;
+  };
+
+  // Count the number of leading zeros in the target RC.
+  unsigned Z = ctlz(RC);
+  if (Z == 0 || Z == W)
+    return false;
+
+  // A simplistic analysis: assume the source register (the one being split)
+  // is fully unknown, and that all its bits are self-references.
+  const BitTracker::BitValue &B0 = RC[0];
+  if (B0.Type != BitTracker::BitValue::Ref)
+    return false;
+
+  unsigned SrcR = B0.RefI.Reg;
+  unsigned SrcSR = 0;
+  unsigned Pos = B0.RefI.Pos;
+
+  // All the non-zero bits should be consecutive bits from the same register.
+  for (unsigned i = 1; i < W-Z; ++i) {
+    const BitTracker::BitValue &V = RC[i];
+    if (V.Type != BitTracker::BitValue::Ref)
+      return false;
+    if (V.RefI.Reg != SrcR || V.RefI.Pos != Pos+i)
+      return false;
+  }
+
+  // Now, find the other bitfield among AVs.
+  for (unsigned S = AVs.find_first(); S; S = AVs.find_next(S)) {
+    // The number of leading zeros here should be the number of trailing
+    // non-zeros in RC.
+    const BitTracker::RegisterCell &SC = BT.lookup(S);
+    if (SC.width() != W || ctlz(SC) != W-Z)
+      continue;
+    // The Z lower bits should now match SrcR.
+    const BitTracker::BitValue &S0 = SC[0];
+    if (S0.Type != BitTracker::BitValue::Ref || S0.RefI.Reg != SrcR)
+      continue;
+    unsigned P = S0.RefI.Pos;
+
+    if (Pos <= P && (Pos + W-Z) != P)
+      continue;
+    if (P < Pos && (P + Z) != Pos)
+      continue;
+    // The starting bitfield position must be at a subregister boundary.
+    if (std::min(P, Pos) != 0 && std::min(P, Pos) != 32)
+      continue;
+
+    unsigned I;
+    for (I = 1; I < Z; ++I) {
+      const BitTracker::BitValue &V = SC[I];
+      if (V.Type != BitTracker::BitValue::Ref)
+        break;
+      if (V.RefI.Reg != SrcR || V.RefI.Pos != P+I)
+        break;
+    }
+    if (I != Z)
+      continue;
+
+    // Generate bitsplit where S is defined.
+    CountBitSplit++;
+    MachineInstr *DefS = MRI.getVRegDef(S);
+    assert(DefS != nullptr);
+    DebugLoc DL = DefS->getDebugLoc();
+    MachineBasicBlock &B = *DefS->getParent();
+    auto At = MI->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 (Pos <= P) {
+      HBS::replaceRegWithSub(RD.Reg, NewR, Hexagon::isub_lo, MRI);
+      HBS::replaceRegWithSub(S,      NewR, Hexagon::isub_hi, MRI);
+    } else {
+      HBS::replaceRegWithSub(S,      NewR, Hexagon::isub_lo, MRI);
+      HBS::replaceRegWithSub(RD.Reg, NewR, Hexagon::isub_hi, MRI);
+    }
+    return true;
+  }
+
+  return false;
+}
+
 // Check for tstbit simplification opportunity, where the bit being checked
 // can be tracked back to another register. For example:
 //   vreg2 = S2_lsr_i_r  vreg1, 5
@@ -2451,7 +2567,8 @@ bool BitSimplification::processBlock(Mac
     }
 
     if (FRC->getID() == Hexagon::IntRegsRegClassID) {
-      bool T = simplifyExtractLow(MI, RD, RC, AVB);
+      bool T = genBitSplit(MI, RD, RC, AVB);
+      T = T || simplifyExtractLow(MI, RD, RC, AVB);
       T = T || genExtractHalf(MI, RD, RC);
       T = T || genCombineHalf(MI, RD, RC);
       T = T || genExtractLow(MI, RD, RC);

Added: llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit-src.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit-src.ll?rev=297239&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit-src.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit-src.ll Tue Mar  7 17:08:35 2017
@@ -0,0 +1,35 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+; REQUIRES: asserts
+
+; This used to crash. Check for some sane output.
+; CHECK: call printf
+
+target triple = "hexagon"
+
+ at g0 = external local_unnamed_addr global [4 x i64], align 8
+ at g1 = external hidden unnamed_addr constant [29 x i8], align 1
+ at g2 = external hidden unnamed_addr constant [29 x i8], align 1
+
+define void @fred() local_unnamed_addr #0 {
+b0:
+  %v1 = load i64, i64* getelementptr inbounds ([4 x i64], [4 x i64]* @g0, i32 0, i32 0), align 8
+  %v2 = trunc i64 %v1 to i32
+  %v3 = lshr i64 %v1, 16
+  %v4 = trunc i64 %v3 to i32
+  %v5 = and i32 %v4, 255
+  %v6 = add nuw nsw i32 0, %v5
+  %v7 = add nuw nsw i32 %v6, 0
+  %v8 = zext i32 %v7 to i64
+  %v9 = and i32 %v2, 65535
+  %v10 = and i32 %v4, 65535
+  %v11 = add nuw nsw i32 %v10, %v9
+  %v12 = zext i32 %v11 to i64
+  tail call void (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @g1, i32 0, i32 0), i64 %v8) #0
+  tail call void (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @g2, i32 0, i32 0), i64 %v12) #0
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @printf(i8* nocapture readonly, ...) local_unnamed_addr #0
+
+attributes #0 = { nounwind "target-cpu"="hexagonv60" "target-features"="-hvx,-hvx-double,-long-calls" }

Added: llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit.ll?rev=297239&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/bit-bitsplit.ll Tue Mar  7 17:08:35 2017
@@ -0,0 +1,17 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+; CHECK: bitsplit(r{{[0-9]+}},#5)
+
+target triple = "hexagon"
+
+define i32 @fred(i32 %a, i32* nocapture readonly %b) local_unnamed_addr #0 {
+entry:
+  %and = and i32 %a, 31
+  %shr = lshr i32 %a, 5
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %shr
+  %0 = load i32, i32* %arrayidx, align 4
+  %shr1 = lshr i32 %0, %and
+  %and2 = and i32 %shr1, 1
+  ret i32 %and2
+}
+
+attributes #0 = { norecurse nounwind readonly "target-cpu"="hexagonv60" "target-features"="-hvx,-hvx-double" }




More information about the llvm-commits mailing list