GlobalISel: Port smarter known bits for umin/umax from DAG
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 27 Aug 2020 22:05:34 +0000 (18:05 -0400)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 1 Sep 2020 16:50:15 +0000 (12:50 -0400)
llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp
llvm/test/CodeGen/AMDGPU/GlobalISel/postlegalizercombiner-and.mir
llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp

index acd8204..82d97fa 100644 (file)
@@ -309,13 +309,43 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known,
     break;
   }
   case TargetOpcode::G_SMIN:
-  case TargetOpcode::G_SMAX:
-  case TargetOpcode::G_UMIN:
-  case TargetOpcode::G_UMAX: {
+  case TargetOpcode::G_SMAX: {
+    // TODO: Handle clamp pattern with number of sign bits
     computeKnownBitsMin(MI.getOperand(1).getReg(), MI.getOperand(2).getReg(),
                         Known, DemandedElts, Depth + 1);
     break;
   }
+  case TargetOpcode::G_UMIN: {
+    KnownBits KnownRHS;
+    computeKnownBitsImpl(MI.getOperand(1).getReg(), Known,
+                         DemandedElts, Depth + 1);
+    computeKnownBitsImpl(MI.getOperand(2).getReg(), KnownRHS,
+                         DemandedElts, Depth + 1);
+
+    // UMIN - we know that the result will have the maximum of the
+    // known zero leading bits of the inputs.
+    unsigned LeadZero = Known.countMinLeadingZeros();
+    LeadZero = std::max(LeadZero, KnownRHS.countMinLeadingZeros());
+    Known &= KnownRHS;
+    Known.Zero.setHighBits(LeadZero);
+    break;
+  }
+  case TargetOpcode::G_UMAX: {
+    KnownBits KnownRHS;
+    computeKnownBitsImpl(MI.getOperand(1).getReg(), Known,
+                         DemandedElts, Depth + 1);
+    computeKnownBitsImpl(MI.getOperand(2).getReg(), KnownRHS,
+                         DemandedElts, Depth + 1);
+
+    // UMAX - we know that the result will have the maximum of the
+    // known one leading bits of the inputs.
+    unsigned LeadOne = Known.countMinLeadingOnes();
+    LeadOne = std::max(LeadOne, KnownRHS.countMinLeadingOnes());
+    Known.Zero &= KnownRHS.Zero;
+    Known.One &= KnownRHS.One;
+    Known.One.setHighBits(LeadOne);
+    break;
+  }
   case TargetOpcode::G_FCMP:
   case TargetOpcode::G_ICMP: {
     if (TL.getBooleanContents(DstTy.isVector(),
index b7491ab..0712052 100644 (file)
@@ -265,3 +265,52 @@ body:             |
     $vgpr0 = COPY %and
 
 ...
+
+# We can conclude the number of bits based only on one operand
+---
+name:  remove_and_umin_lhs_only
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4
+
+    ; CHECK-LABEL: name: remove_and_umin_lhs_only
+    ; CHECK: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4
+    ; CHECK: %val:_(s32) = COPY $vgpr4
+    ; CHECK: %k255:_(s32) = G_CONSTANT i32 255
+    ; CHECK: %umin0:_(s32) = G_UMIN %val, %k255
+    ; CHECK: $vgpr0 = COPY %umin0(s32)
+    %ptr0:_(p1) = COPY $vgpr0_vgpr1
+    %ptr1:_(p1) = COPY $vgpr2_vgpr3
+    %val:_(s32) = COPY $vgpr4
+    %k255:_(s32) = G_CONSTANT i32 255
+    %umin0:_(s32) = G_UMIN %val, %k255
+    %and:_(s32) = G_AND %umin0, %k255
+    $vgpr0 = COPY %and
+
+...
+
+---
+name:  remove_and_umin_rhs_only
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4
+
+    ; CHECK-LABEL: name: remove_and_umin_rhs_only
+    ; CHECK: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3, $vgpr4
+    ; CHECK: %val:_(s32) = COPY $vgpr4
+    ; CHECK: %k255:_(s32) = G_CONSTANT i32 255
+    ; CHECK: %umin0:_(s32) = G_UMIN %k255, %val
+    ; CHECK: $vgpr0 = COPY %umin0(s32)
+    %ptr0:_(p1) = COPY $vgpr0_vgpr1
+    %ptr1:_(p1) = COPY $vgpr2_vgpr3
+    %val:_(s32) = COPY $vgpr4
+    %k255:_(s32) = G_CONSTANT i32 255
+    %umin0:_(s32) = G_UMIN %k255, %val
+    %and:_(s32) = G_AND %umin0, %k255
+    $vgpr0 = COPY %and
+
+...
index 92dc57b..30ff375 100644 (file)
@@ -701,3 +701,27 @@ TEST_F(AArch64GISelMITest, TestKnownBitsBSwapBitReverse) {
   EXPECT_EQ(TestVal, BitReverseKnown.One.getZExtValue());
   EXPECT_EQ(~TestVal, BitReverseKnown.Zero.getZExtValue());
 }
+
+TEST_F(AArch64GISelMITest, TestKnownBitsUMax) {
+  StringRef MIRString = R"(
+   %val:_(s32) = COPY $w0
+   %zext:_(s64) = G_ZEXT %val
+   %const:_(s64) = G_CONSTANT i64 -256
+   %umax:_(s64) = G_UMAX %zext, %const
+   %copy_umax:_(s64) = COPY %umax
+)";
+  setUp(MIRString);
+  if (!TM)
+    return;
+
+  Register CopyUMax = Copies[Copies.size() - 1];
+  GISelKnownBits Info(*MF);
+
+  KnownBits KnownUmax = Info.getKnownBits(CopyUMax);
+  EXPECT_EQ(64u, KnownUmax.getBitWidth());
+  EXPECT_EQ(0u, KnownUmax.Zero.getZExtValue());
+  EXPECT_EQ(0xffffffffffffff00, KnownUmax.One.getZExtValue());
+
+  EXPECT_EQ(0u, KnownUmax.Zero.getZExtValue());
+  EXPECT_EQ(0xffffffffffffff00, KnownUmax.One.getZExtValue());
+}