[llvm] r284501 - [SCEV] Make CompareValueComplexity a little bit smarter

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 18 10:45:16 PDT 2016


Author: sanjoy
Date: Tue Oct 18 12:45:16 2016
New Revision: 284501

URL: http://llvm.org/viewvc/llvm-project?rev=284501&view=rev
Log:
[SCEV] Make CompareValueComplexity a little bit smarter

This helps canonicalization in some cases.

Thanks to Pankaj Chawla for the investigation and the test case!

Modified:
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=284501&r1=284500&r2=284501&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Tue Oct 18 12:45:16 2016
@@ -449,7 +449,10 @@ bool SCEVUnknown::isOffsetOf(Type *&CTy,
 //===----------------------------------------------------------------------===//
 
 static int CompareValueComplexity(const LoopInfo *const LI, Value *LV,
-                                  Value *RV) {
+                                  Value *RV, unsigned DepthLeft = 2) {
+  if (DepthLeft == 0)
+    return 0;
+
   // Order pointer values after integer values. This helps SCEVExpander form
   // GEPs.
   bool LIsPointer = LV->getType()->isPointerTy(),
@@ -487,7 +490,14 @@ static int CompareValueComplexity(const
     // Compare the number of operands.
     unsigned LNumOps = LInst->getNumOperands(),
              RNumOps = RInst->getNumOperands();
-    return (int)LNumOps - (int)RNumOps;
+    if (LNumOps != RNumOps || LNumOps != 1)
+      return (int)LNumOps - (int)RNumOps;
+
+    // We only bother "recursing" if we have one operand to look at (so we don't
+    // really recurse as much as we iterate).  We can consider expanding this
+    // logic in the future.
+    return CompareValueComplexity(LI, LInst->getOperand(0),
+                                  RInst->getOperand(0), DepthLeft - 1);
   }
 
   return 0;

Modified: llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp?rev=284501&r1=284500&r2=284501&view=diff
==============================================================================
--- llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp (original)
+++ llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp Tue Oct 18 12:45:16 2016
@@ -14,12 +14,16 @@
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InstIterator.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 
 namespace llvm {
@@ -329,5 +333,113 @@ TEST_F(ScalarEvolutionsTest, ExpandPtrTy
   EXPECT_TRUE(isa<BitCastInst>(Gep->getPrevNode()));
 }
 
+static Instruction *getInstructionByName(Module &M, StringRef Name) {
+  for (auto &F : M)
+    for (auto &I : instructions(F))
+      if (I.getName() == Name)
+        return &I;
+  llvm_unreachable("Expected to find instruction!");
+}
+
+TEST_F(ScalarEvolutionsTest, CommutativeExprOperandOrder) {
+  LLVMContext C;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M = parseAssemblyString(
+      "target datalayout = \"e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128\" "
+      "define void @foo(i8* nocapture %arr, i32 %n, i32* %A, i32* %B) "
+      "    local_unnamed_addr { "
+      "entry: "
+      "  %entrycond = icmp sgt i32 %n, 0 "
+      "  br i1 %entrycond, label %loop.ph, label %for.end "
+      " "
+      "loop.ph: "
+      "  %a = load i32, i32* %A, align 4 "
+      "  %b = load i32, i32* %B, align 4 "
+      "  %mul = mul nsw i32 %b, %a "
+      "  %iv0.init = getelementptr inbounds i8, i8* %arr, i32 %mul "
+      "  br label %loop "
+      " "
+      "loop: "
+      "  %iv0 = phi i8* [ %iv0.inc, %loop ], [ %iv0.init, %loop.ph ] "
+      "  %iv1 = phi i32 [ %iv1.inc, %loop ], [ 0, %loop.ph ] "
+      "  %conv = trunc i32 %iv1 to i8 "
+      "  store i8 %conv, i8* %iv0, align 1 "
+      "  %iv0.inc = getelementptr inbounds i8, i8* %iv0, i32 %b "
+      "  %iv1.inc = add nuw nsw i32 %iv1, 1 "
+      "  %exitcond = icmp eq i32 %iv1.inc, %n "
+      "  br i1 %exitcond, label %for.end.loopexit, label %loop "
+      " "
+      "for.end.loopexit: "
+      "  br label %for.end "
+      " "
+      "for.end: "
+      "  ret void "
+      "} "
+      " "
+      "define void @bar(i32* %X, i32* %Y, i32* %Z) { "
+      "  %x = load i32, i32* %X "
+      "  %y = load i32, i32* %Y "
+      "  %z = load i32, i32* %Z "
+      "  ret void "
+      "} ",
+      Err, C);
+
+  assert(M && "Could not parse module?");
+  assert(!verifyModule(*M) && "Must have been well formed!");
+
+  {
+    auto *IV0 = getInstructionByName(*M, "iv0");
+    auto *IV0Inc = getInstructionByName(*M, "iv0.inc");
+
+    auto *F = M->getFunction("foo");
+    assert(F && "Expected!");
+
+    ScalarEvolution SE = buildSE(*F);
+    auto *FirstExprForIV0 = SE.getSCEV(IV0);
+    auto *FirstExprForIV0Inc = SE.getSCEV(IV0Inc);
+    auto *SecondExprForIV0 = SE.getSCEV(IV0);
+
+    EXPECT_TRUE(isa<SCEVAddRecExpr>(FirstExprForIV0));
+    EXPECT_TRUE(isa<SCEVAddRecExpr>(FirstExprForIV0Inc));
+    EXPECT_TRUE(isa<SCEVAddRecExpr>(SecondExprForIV0));
+  }
+
+  {
+    auto *F = M->getFunction("bar");
+    assert(F && "Expected!");
+
+    ScalarEvolution SE = buildSE(*F);
+
+    auto *LoadArg0 = SE.getSCEV(getInstructionByName(*M, "x"));
+    auto *LoadArg1 = SE.getSCEV(getInstructionByName(*M, "y"));
+    auto *LoadArg2 = SE.getSCEV(getInstructionByName(*M, "z"));
+
+    auto *MulA = SE.getMulExpr(LoadArg0, LoadArg1);
+    auto *MulB = SE.getMulExpr(LoadArg1, LoadArg0);
+
+    EXPECT_EQ(MulA, MulB);
+
+    SmallVector<const SCEV *, 3> Ops0 = { LoadArg0, LoadArg1, LoadArg2 };
+    SmallVector<const SCEV *, 3> Ops1 = { LoadArg0, LoadArg2, LoadArg1 };
+    SmallVector<const SCEV *, 3> Ops2 = { LoadArg1, LoadArg0, LoadArg2 };
+    SmallVector<const SCEV *, 3> Ops3 = { LoadArg1, LoadArg2, LoadArg0 };
+    SmallVector<const SCEV *, 3> Ops4 = { LoadArg2, LoadArg1, LoadArg0 };
+    SmallVector<const SCEV *, 3> Ops5 = { LoadArg2, LoadArg0, LoadArg1 };
+
+    auto *Mul0 = SE.getMulExpr(Ops0);
+    auto *Mul1 = SE.getMulExpr(Ops1);
+    auto *Mul2 = SE.getMulExpr(Ops2);
+    auto *Mul3 = SE.getMulExpr(Ops3);
+    auto *Mul4 = SE.getMulExpr(Ops4);
+    auto *Mul5 = SE.getMulExpr(Ops5);
+
+    EXPECT_EQ(Mul0, Mul1);
+    EXPECT_EQ(Mul1, Mul2);
+    EXPECT_EQ(Mul2, Mul3);
+    EXPECT_EQ(Mul3, Mul4);
+    EXPECT_EQ(Mul4, Mul5);
+  }
+}
+
 }  // end anonymous namespace
 }  // end namespace llvm




More information about the llvm-commits mailing list