GlobalISel: Start adding computeNumSignBits to GISelKnownBits
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Sat, 4 Jan 2020 19:13:06 +0000 (14:13 -0500)
committerMatt Arsenault <arsenm2@gmail.com>
Mon, 6 Jan 2020 22:21:51 +0000 (17:21 -0500)
llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h
llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp
llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp

index dfe5a7f..d44612f 100644 (file)
@@ -40,6 +40,10 @@ public:
                                     const APInt &DemandedElts,
                                     unsigned Depth = 0);
 
+  unsigned computeNumSignBits(Register R, const APInt &DemandedElts,
+                              unsigned Depth = 0);
+  unsigned computeNumSignBits(Register R, unsigned Depth = 0);
+
   // KnownBitsAPI
   KnownBits getKnownBits(Register R);
   // Calls getKnownBits for first operand def of MI.
index 41ef631..64023ec 100644 (file)
@@ -373,6 +373,76 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known,
                     << Known.One.toString(16, false) << "\n");
 }
 
+unsigned GISelKnownBits::computeNumSignBits(Register R,
+                                            const APInt &DemandedElts,
+                                            unsigned Depth) {
+  MachineInstr &MI = *MRI.getVRegDef(R);
+  unsigned Opcode = MI.getOpcode();
+
+  if (Opcode == TargetOpcode::G_CONSTANT)
+    return MI.getOperand(1).getCImm()->getValue().getNumSignBits();
+
+  if (Depth == getMaxDepth())
+    return 1;
+
+  if (!DemandedElts)
+    return 1; // No demanded elts, better to assume we don't know anything.
+
+  LLT DstTy = MRI.getType(R);
+
+  // Handle the case where this is called on a register that does not have a
+  // type constraint. This is unlikely to occur except by looking through copies
+  // but it is possible for the initial register being queried to be in this
+  // state.
+  if (!DstTy.isValid())
+    return 1;
+
+  switch (Opcode) {
+  case TargetOpcode::COPY: {
+    MachineOperand &Src = MI.getOperand(1);
+    if (Src.getReg().isVirtual() && Src.getSubReg() == 0 &&
+        MRI.getType(Src.getReg()).isValid()) {
+      // Don't increment Depth for this one since we didn't do any work.
+      return computeNumSignBits(Src.getReg(), DemandedElts, Depth);
+    }
+
+    return 1;
+  }
+  case TargetOpcode::G_SEXT: {
+    Register Src = MI.getOperand(1).getReg();
+    LLT SrcTy = MRI.getType(Src);
+    unsigned Tmp = DstTy.getScalarSizeInBits() - SrcTy.getScalarSizeInBits();
+    return computeNumSignBits(Src, DemandedElts, Depth + 1) + Tmp;
+  }
+  case TargetOpcode::G_TRUNC: {
+    Register Src = MI.getOperand(1).getReg();
+    LLT SrcTy = MRI.getType(Src);
+
+    // Check if the sign bits of source go down as far as the truncated value.
+    unsigned DstTyBits = DstTy.getScalarSizeInBits();
+    unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
+    unsigned NumSrcSignBits = computeNumSignBits(Src, DemandedElts, Depth + 1);
+    if (NumSrcSignBits > (NumSrcBits - DstTyBits))
+      return NumSrcSignBits - (NumSrcBits - DstTyBits);
+    break;
+  }
+  default:
+    break;
+  }
+
+  // TODO: Handle target instructions
+  // TODO: Fall back to known bits
+  return 1;
+}
+
+unsigned GISelKnownBits::computeNumSignBits(Register R, unsigned Depth) {
+  LLT Ty = MRI.getType(R);
+  APInt DemandedElts = Ty.isVector()
+                           ? APInt::getAllOnesValue(Ty.getNumElements())
+                           : APInt(1, 1);
+  return computeNumSignBits(R, DemandedElts, Depth);
+}
+
 void GISelKnownBitsAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
   MachineFunctionPass::getAnalysisUsage(AU);
index f7b0378..e6c92f3 100644 (file)
@@ -133,3 +133,81 @@ TEST_F(GISelMITest, TestSignBitIsZero) {
   EXPECT_TRUE(KnownBits.signBitIsZero(Zero.getReg(0)));
   EXPECT_FALSE(KnownBits.signBitIsZero(SignBit.getReg(0)));
 }
+
+TEST_F(GISelMITest, TestNumSignBitsConstant) {
+  StringRef MIRString = "  %3:_(s8) = G_CONSTANT i8 1\n"
+                        "  %4:_(s8) = COPY %3\n"
+
+                        "  %5:_(s8) = G_CONSTANT i8 -1\n"
+                        "  %6:_(s8) = COPY %5\n"
+
+                        "  %7:_(s8) = G_CONSTANT i8 127\n"
+                        "  %8:_(s8) = COPY %7\n"
+
+                        "  %9:_(s8) = G_CONSTANT i8 32\n"
+                        "  %10:_(s8) = COPY %9\n"
+
+                        "  %11:_(s8) = G_CONSTANT i8 -32\n"
+                        "  %12:_(s8) = COPY %11\n";
+  setUp(MIRString);
+  if (!TM)
+    return;
+  Register CopyReg1 = Copies[Copies.size() - 5];
+  Register CopyRegNeg1 = Copies[Copies.size() - 4];
+  Register CopyReg127 = Copies[Copies.size() - 3];
+  Register CopyReg32 = Copies[Copies.size() - 2];
+  Register CopyRegNeg32 = Copies[Copies.size() - 1];
+
+  GISelKnownBits Info(*MF);
+  EXPECT_EQ(7u, Info.computeNumSignBits(CopyReg1));
+  EXPECT_EQ(8u, Info.computeNumSignBits(CopyRegNeg1));
+  EXPECT_EQ(1u, Info.computeNumSignBits(CopyReg127));
+  EXPECT_EQ(2u, Info.computeNumSignBits(CopyReg32));
+  EXPECT_EQ(3u, Info.computeNumSignBits(CopyRegNeg32));
+}
+
+TEST_F(GISelMITest, TestNumSignBitsSext) {
+  StringRef MIRString = "  %3:_(p0) = G_IMPLICIT_DEF\n"
+                        "  %4:_(s8) = G_LOAD %3 :: (load 1)\n"
+                        "  %5:_(s32) = G_SEXT %4\n"
+                        "  %6:_(s32) = COPY %5\n"
+
+                        "  %7:_(s8) = G_CONSTANT i8 -1\n"
+                        "  %8:_(s32) = G_SEXT %7\n"
+                        "  %9:_(s32) = COPY %8\n";
+  setUp(MIRString);
+  if (!TM)
+    return;
+  Register CopySextLoad = Copies[Copies.size() - 2];
+  Register CopySextNeg1 = Copies[Copies.size() - 1];
+
+  GISelKnownBits Info(*MF);
+  EXPECT_EQ(25u, Info.computeNumSignBits(CopySextLoad));
+  EXPECT_EQ(32u, Info.computeNumSignBits(CopySextNeg1));
+}
+
+TEST_F(GISelMITest, TestNumSignBitsTrunc) {
+  StringRef MIRString = "  %3:_(p0) = G_IMPLICIT_DEF\n"
+                        "  %4:_(s32) = G_LOAD %3 :: (load 4)\n"
+                        "  %5:_(s8) = G_TRUNC %4\n"
+                        "  %6:_(s8) = COPY %5\n"
+
+                        "  %7:_(s32) = G_CONSTANT i32 -1\n"
+                        "  %8:_(s8) = G_TRUNC %7\n"
+                        "  %9:_(s8) = COPY %8\n"
+
+                        "  %10:_(s32) = G_CONSTANT i32 7\n"
+                        "  %11:_(s8) = G_TRUNC %10\n"
+                        "  %12:_(s8) = COPY %11\n";
+  setUp(MIRString);
+  if (!TM)
+    return;
+  Register CopyTruncLoad = Copies[Copies.size() - 3];
+  Register CopyTruncNeg1 = Copies[Copies.size() - 2];
+  Register CopyTrunc7 = Copies[Copies.size() - 1];
+
+  GISelKnownBits Info(*MF);
+  EXPECT_EQ(1u, Info.computeNumSignBits(CopyTruncLoad));
+  EXPECT_EQ(8u, Info.computeNumSignBits(CopyTruncNeg1));
+  EXPECT_EQ(5u, Info.computeNumSignBits(CopyTrunc7));
+}