[PATCH] D46760: [InstCombine] Enhance narrowUDivURem.

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


bixia created this revision.
Herald added subscribers: llvm-commits, jlebar, sanjoy.

Transform udiv/urem (zext X), C to zext (udiv/urem X, C') when X has two uses
and both uses can be transformed. This is a common pattern seen in code
generated by the XLA GPU backend.

Add a test case.


Repository:
  rL LLVM

https://reviews.llvm.org/D46760

Files:
  lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
  test/Transforms/InstCombine/narrow.ll
  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,21 @@
   ret <2 x i32> %udiv
 }
 
+define i64 @udiv_urem_twouses(i32 %a) {
+; CHECK-LABEL: @udiv_urem_twouses(
+; 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 i32 @udiv_i32_multiuse(i8 %a, i8 %b) {
 ; CHECK-LABEL: @udiv_i32_multiuse(
 ; CHECK-NEXT:    [[ZA:%.*]] = zext i8 %a to i32
Index: test/Transforms/InstCombine/narrow.ll
===================================================================
--- test/Transforms/InstCombine/narrow.ll
+++ test/Transforms/InstCombine/narrow.ll
@@ -236,4 +236,3 @@
   %logic = xor i32 %zext, %phi
   ret i32 %logic
 }
-
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.146346.patch
Type: text/x-patch
Size: 2931 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180511/53c1864b/attachment.bin>


More information about the llvm-commits mailing list