[PATCH] D46760: [InstCombine] Enhance narrowUDivURem.

Bixia Zheng via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri May 11 10:46:31 PDT 2018


bixia updated this revision to Diff 146358.
bixia added a comment.

Add another test case.


Repository:
  rL LLVM

https://reviews.llvm.org/D46760

Files:
  lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
  test/Transforms/InstCombine/udivrem-change-width.ll


Index: test/Transforms/InstCombine/udivrem-change-width.ll
===================================================================
--- test/Transforms/InstCombine/udivrem-change-width.ll
+++ test/Transforms/InstCombine/udivrem-change-width.ll
@@ -75,6 +75,36 @@
   ret <2 x i32> %udiv
 }
 
+define i64 @udiv_urem_twouses_xform(i32 %a) {
+; CHECK-LABEL: @udiv_urem_twouses_xform(
+; CHECK-NEXT:    [[UDIV:%.*]] = udiv i32 [[A:%.*]], 33
+; CHECK-NEXT:    [[UREM:%.*]] = urem i32 [[A:%.*]], 33
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[UDIV]], [[UREM]]
+; CHECK-NEXT:    [[ADD_ZEXT:%.*]] = zext i32 [[ADD:%.*]] to i64
+; CHECK-NEXT:    ret i64 [[ADD_ZEXT]]
+;
+  %za = zext i32 %a to i64
+  %udiv = udiv i64 %za, 33
+  %urem = urem i64 %za, 33
+  %uadd = add i64 %udiv, %urem
+  ret i64 %uadd
+}
+
+define i64 @udiv_urem_twouses_not_xform(i32 %a) {
+; CHECK-LABEL: @udiv_urem_twouses_not_xform(
+; CHECK-NEXT:    [[A_ZEXT:%.*]] = zext i32 {{%.*}} to i64
+; CHECK-NEXT:    [[UDIV:%.*]] = udiv i64 [[A_ZEXT:%.*]], 33
+; CHECK-NEXT:    [[UREM:%.*]] = urem i64 [[A_ZEXT:%.*]], 2147483649
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i64 [[UDIV]], [[UREM]]
+; CHECK-NEXT:    ret i64 [[ADD]]
+;
+  %za = zext i32 %a to i64
+  %udiv = udiv i64 %za, 33
+  %urem = urem i64 %za, 2147483649
+  %uadd = add i64 %udiv, %urem
+  ret i64 %uadd
+}
+
 define i32 @udiv_i32_multiuse(i8 %a, i8 %b) {
 ; CHECK-LABEL: @udiv_i32_multiuse(
 ; CHECK-NEXT:    [[ZA:%.*]] = zext i8 %a to i32
Index: lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -918,8 +918,34 @@
   }
 
   Constant *C;
-  if ((match(N, m_OneUse(m_ZExt(m_Value(X)))) && match(D, m_Constant(C))) ||
-      (match(D, m_OneUse(m_ZExt(m_Value(X)))) && match(N, m_Constant(C)))) {
+  bool CanConvert = false;
+  if ((match(N, m_ZExt(m_Value(X))) && match(D, m_Constant(C)))) {
+    if (N->hasOneUse()) {
+      CanConvert = true;
+    } else if (N->hasNUses(2)) {
+      // Handle the case with two uses to support this common pattern:
+      //   warp_id = N UDIV 32
+      //   lane_id = N UREM 32
+      Value::user_iterator UI = N->user_begin();
+      llvm::Instruction *I1 =
+          dyn_cast<llvm::Instruction>(*UI);
+      llvm::Instruction *I2 =
+          dyn_cast<llvm::Instruction>(*(++UI));
+      I2 = (I1 == &I) ? I2 : I1;
+      // Instead of allowing a second constant C2 that meets the requirement of
+      // ConstantExpr::getZExt(Trunc(C2), Ty) == C2, we simply require the
+      // constant to be the same as the first constant.
+      if (I2 && (match(I2, m_UDiv(m_Specific(N), m_Specific(C))) ||
+                 match(I2, m_URem(m_Specific(N), m_Specific(C))))) {
+        CanConvert = true;
+      }
+    }
+  } else if (match(D, m_OneUse(m_ZExt(m_Value(X)))) &&
+             match(N, m_Constant(C))) {
+    CanConvert = true;
+  }
+
+  if (CanConvert) {
     // If the constant is the same in the smaller type, use the narrow version.
     Constant *TruncC = ConstantExpr::getTrunc(C, X->getType());
     if (ConstantExpr::getZExt(TruncC, Ty) != C)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D46760.146358.patch
Type: text/x-patch
Size: 3206 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180511/080374c9/attachment.bin>


More information about the llvm-commits mailing list