[llvm] r338251 - [Hexagon] Simplify A4_rcmp[n]eqi R, 0

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 30 07:28:02 PDT 2018


Author: kparzysz
Date: Mon Jul 30 07:28:02 2018
New Revision: 338251

URL: http://llvm.org/viewvc/llvm-project?rev=338251&view=rev
Log:
[Hexagon] Simplify A4_rcmp[n]eqi R, 0

Consider cases when register R is known to be zero/non-zero, or when it
is defined by a C2_muxii instruction.

Added:
    llvm/trunk/test/CodeGen/Hexagon/bit-cmp0.mir
Modified:
    llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp
    llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.cpp
    llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.h

Modified: llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp?rev=338251&r1=338250&r2=338251&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonBitSimplify.cpp Mon Jul 30 07:28:02 2018
@@ -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::simplifyExtractL
   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(Mac
       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;
     }

Modified: llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.cpp?rev=338251&r1=338250&r2=338251&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.cpp Mon Jul 30 07:28:02 2018
@@ -347,9 +347,11 @@ bool HexagonEvaluator::evaluate(const Ma
       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 Ma
     }
 
     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 Ma
   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 {

Modified: llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.h?rev=338251&r1=338250&r2=338251&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.h (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonBitTracker.h Mon Jul 30 07:28:02 2018
@@ -49,6 +49,7 @@ struct HexagonEvaluator : public BitTrac
   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,

Added: llvm/trunk/test/CodeGen/Hexagon/bit-cmp0.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/bit-cmp0.mir?rev=338251&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/bit-cmp0.mir (added)
+++ llvm/trunk/test/CodeGen/Hexagon/bit-cmp0.mir Mon Jul 30 07:28:02 2018
@@ -0,0 +1,154 @@
+# RUN: llc -march=hexagon -run-pass hexagon-bit-simplify -o - %s | FileCheck %s
+
+--- |
+  @g0 = global i32 0, align 4
+
+  define i32 @f0() { ret i32 0 }
+  define i32 @f1() { ret i32 0 }
+  define i32 @f2() { ret i32 0 }
+  define i32 @f3() { ret i32 0 }
+  define i32 @f4() { ret i32 0 }
+  define i32 @f5() { ret i32 0 }
+  define i32 @f6() { ret i32 0 }
+  define i32 @f7() { ret i32 0 }
+...
+
+# Case 0: is-zero with known zero register
+# CHECK-LABEL: name: f0
+# CHECK: %[[R00:[0-9]+]]:intregs = A2_tfrsi 1
+# CHECK: $r0 = COPY %[[R00]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f0
+tracksRegLiveness: true
+body: |
+  bb.0:
+    %0:intregs = A2_tfrsi 0
+    %2:intregs = A4_rcmpeqi killed %0, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+
+# Case 1: is-zero with known non-zero register
+# CHECK-LABEL: name: f1
+# CHECK: %[[R10:[0-9]+]]:intregs = A2_tfrsi 0
+# CHECK: $r0 = COPY %[[R10]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f1
+tracksRegLiveness: true
+body: |
+  bb.0:
+    %0:intregs = A2_tfrsi 128
+    %2:intregs = A4_rcmpeqi killed %0, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+
+# Case 2: is-not-zero with known zero register
+# CHECK-LABEL: name: f2
+# CHECK: %[[R20:[0-9]+]]:intregs = A2_tfrsi 0
+# CHECK: $r0 = COPY %[[R20]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f2
+tracksRegLiveness: true
+body: |
+  bb.0:
+    %0:intregs = A2_tfrsi 0
+    %2:intregs = A4_rcmpneqi killed %0, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+
+# Case 3: is-not-zero with known non-zero register
+# CHECK-LABEL: name: f3
+# CHECK: %[[R30:[0-9]+]]:intregs = A2_tfrsi 1
+# CHECK: $r0 = COPY %[[R30]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f3
+tracksRegLiveness: true
+body: |
+  bb.0:
+    %0:intregs = A2_tfrsi 1024
+    %2:intregs = A4_rcmpneqi killed %0, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+
+
+# Case 4: is-zero with mux(p, 1, 0)
+# CHECK-LABEL: name: f4
+# CHECK: %[[R40:[0-9]+]]:predregs = COPY $p0
+# CHECK: %[[R41:[0-9]+]]:intregs = C2_muxii %[[R40]], 0, 1
+# CHECK: $r0 = COPY %[[R41]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f4
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $p0
+    %0:predregs = COPY $p0
+    %1:intregs = C2_muxii %0, 1, 0
+    %2:intregs = A4_rcmpeqi killed %1, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+
+# Case 5: is-zero with mux(p, 0, 1)
+# CHECK-LABEL: name: f5
+# CHECK: %[[R50:[0-9]+]]:predregs = COPY $p0
+# CHECK: %[[R51:[0-9]+]]:intregs = C2_muxii %[[R50]], 1, 0
+# CHECK: $r0 = COPY %[[R51]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f5
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $p0
+    %0:predregs = COPY $p0
+    %1:intregs = C2_muxii %0, 0, 1
+    %2:intregs = A4_rcmpeqi killed %1, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+
+# Case 6: is-not-zero with mux(p, 1, 2)
+# CHECK-LABEL: name: f6
+# CHECK: %[[R60:[0-9]+]]:intregs = A2_tfrsi 1
+# CHECK: $r0 = COPY %[[R60]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f6
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $p0
+    %0:predregs = COPY $p0
+    %1:intregs = C2_muxii %0, 1, 2
+    %2:intregs = A4_rcmpneqi killed %1, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+
+# Case 7: is-not-zero with mux(p, @g0, 2)
+# CHECK-LABEL: name: f7
+# CHECK: %[[R70:[0-9]+]]:intregs = A2_tfrsi 1
+# CHECK: $r0 = COPY %[[R70]]
+# CHECK: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+
+name: f7
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $p0
+    %0:predregs = COPY $p0
+    %1:intregs = C2_muxii %0, @g0, 2
+    %2:intregs = A4_rcmpneqi killed %1, 0
+    $r0 = COPY %2
+    PS_jmpret $r31, implicit-def dead $pc, implicit $r0
+...
+




More information about the llvm-commits mailing list