[llvm] r334737 - [SCEV] Simplify zext/trunc idiom that appears when handling bitmasks.

Justin Lebar via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 14 10:13:48 PDT 2018


Author: jlebar
Date: Thu Jun 14 10:13:48 2018
New Revision: 334737

URL: http://llvm.org/viewvc/llvm-project?rev=334737&view=rev
Log:
[SCEV] Simplify zext/trunc idiom that appears when handling bitmasks.

Summary:
Specifically, we transform

  zext(2^K * (trunc X to iN)) to iM ->
  2^K * (zext(trunc X to i{N-K}) to iM)<nuw>

This is helpful because pulling the 2^K out of the zext allows further
optimizations.

Reviewers: sanjoy

Subscribers: hiraditya, llvm-commits, timshen

Differential Revision: https://reviews.llvm.org/D48158

Modified:
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll
    llvm/trunk/test/Analysis/ScalarEvolution/and-xor.ll

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=334737&r1=334736&r2=334737&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Jun 14 10:13:48 2018
@@ -1778,6 +1778,32 @@ ScalarEvolution::getZeroExtendExpr(const
         Ops.push_back(getZeroExtendExpr(Op, Ty, Depth + 1));
       return getMulExpr(Ops, SCEV::FlagNUW, Depth + 1);
     }
+
+    // zext(2^K * (trunc X to iN)) to iM ->
+    // 2^K * (zext(trunc X to i{N-K}) to iM)<nuw>
+    //
+    // Proof:
+    //
+    //     zext(2^K * (trunc X to iN)) to iM
+    //   = zext((trunc X to iN) << K) to iM
+    //   = zext((trunc X to i{N-K}) << K)<nuw> to iM
+    //     (because shl removes the top K bits)
+    //   = zext((2^K * (trunc X to i{N-K}))<nuw>) to iM
+    //   = (2^K * (zext(trunc X to i{N-K}) to iM))<nuw>.
+    //
+    if (SA->getNumOperands() == 2)
+      if (auto *MulLHS = dyn_cast<SCEVConstant>(SA->getOperand(0)))
+        if (MulLHS->getAPInt().isPowerOf2())
+          if (auto *TruncRHS = dyn_cast<SCEVTruncateExpr>(SA->getOperand(1))) {
+            int NewTruncBits = getTypeSizeInBits(TruncRHS->getType()) -
+                               MulLHS->getAPInt().logBase2();
+            Type *NewTruncTy = IntegerType::get(getContext(), NewTruncBits);
+            return getMulExpr(
+                getZeroExtendExpr(MulLHS, Ty),
+                getZeroExtendExpr(
+                    getTruncateExpr(TruncRHS->getOperand(), NewTruncTy), Ty),
+                SCEV::FlagNUW, Depth + 1);
+          }
   }
 
   // The cast wasn't folded; create an explicit cast node.

Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll?rev=334737&r1=334736&r2=334737&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll (original)
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll Thu Jun 14 10:13:48 2018
@@ -122,7 +122,7 @@ for.end:
 ; LAA: Memory dependences are safe{{$}}
 ; LAA: SCEV assumptions:
 ; LAA-NEXT: {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> Added Flags: <nusw>
-; LAA-NEXT: {((2 * (zext i32 (2 * (trunc i64 %N to i32)) to i64))<nuw> + %a),+,-4}<%for.body> Added Flags: <nusw>
+; LAA-NEXT: {((4 * (zext i31 (trunc i64 %N to i31) to i64)) + %a),+,-4}<%for.body> Added Flags: <nusw>
 
 ; The expression for %mul_ext as analyzed by SCEV is
 ;     (zext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64)
@@ -131,7 +131,7 @@ for.end:
 
 ; LAA: [PSE]  %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext:
 ; LAA-NEXT: ((2 * (zext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64))<nuw> + %a)
-; LAA-NEXT: --> {((2 * (zext i32 (2 * (trunc i64 %N to i32)) to i64))<nuw> + %a),+,-4}<%for.body>
+; LAA-NEXT: --> {((4 * (zext i31 (trunc i64 %N to i31) to i64)) + %a),+,-4}<%for.body>
 
 ; LV-LABEL: f2
 ; LV-LABEL: for.body.lver.check

Modified: llvm/trunk/test/Analysis/ScalarEvolution/and-xor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/and-xor.ll?rev=334737&r1=334736&r2=334737&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/and-xor.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/and-xor.ll Thu Jun 14 10:13:48 2018
@@ -25,3 +25,17 @@ define i64 @test2(i64 %x) {
   %z = xor i64 %t, 8
   ret i64 %z
 }
+
+; Check that we transform the naive lowering of the sequence below,
+;   (4 * (zext i5 (2 * (trunc i32 %x to i5)) to i32)),
+; to
+;   (8 * (zext i4 (trunc i32 %x to i4) to i32))
+;
+; CHECK-LABEL: @test3
+define i32 @test3(i32 %x) {
+  %a = mul i32 %x, 8
+; CHECK: %b
+; CHECK-NEXT: --> (8 * (zext i4 (trunc i32 %x to i4) to i32))
+  %b = and i32 %a, 124
+  ret i32 %b
+}




More information about the llvm-commits mailing list