[PATCH] D64122: Fix for PR42397. SCEVExpander wrongly adds nsw to shl instruction.

Denis Bakhvalov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 3 01:07:07 PDT 2019


dendibakh created this revision.
dendibakh added reviewers: eli.friedman, samparker.
Herald added subscribers: llvm-commits, sanjoy, hiraditya.
Herald added a project: LLVM.

Introduced by rL363540 <https://reviews.llvm.org/rL363540>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64122

Files:
  llvm/lib/Analysis/ScalarEvolutionExpander.cpp
  llvm/unittests/Analysis/ScalarEvolutionTest.cpp


Index: llvm/unittests/Analysis/ScalarEvolutionTest.cpp
===================================================================
--- llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -1637,5 +1637,46 @@
   TestMatchingCanonicalIV(GetAR2, ARBitWidth);
 }
 
+TEST_F(ScalarEvolutionsTest, SCEVExpanderShlNSW) {
+
+  auto checkOneCase = [this](std::string &&str) {
+    LLVMContext C;
+    SMDiagnostic Err;
+    std::unique_ptr<Module> M = parseAssemblyString(str, Err, C);
+
+    assert(M && "Could not parse module?");
+    assert(!verifyModule(*M) && "Must have been well formed!");
+
+    Function *F = M->getFunction("f");
+    ASSERT_NE(F, nullptr) << "Could not find function 'f'";
+
+    BasicBlock &Entry = F->getEntryBlock();
+    LoadInst *Load = cast<LoadInst>(&Entry.front());
+    BinaryOperator *And = cast<BinaryOperator>(*Load->user_begin());
+
+    ScalarEvolution SE = buildSE(*F);
+    const SCEV *AndSCEV = SE.getSCEV(And);
+    EXPECT_TRUE(isa<SCEVMulExpr>(AndSCEV));
+    EXPECT_TRUE(cast<SCEVMulExpr>(AndSCEV)->hasNoSignedWrap());
+
+    SCEVExpander Exp(SE, M->getDataLayout(), "expander");
+    auto *I = cast<Instruction>(Exp.expandCodeFor(AndSCEV, nullptr, And));
+    EXPECT_EQ(I->getOpcode(), Instruction::Shl);
+    EXPECT_FALSE(I->hasNoSignedWrap());
+  };
+
+  checkOneCase("define void @f(i16* %arrayidx) { "
+               "  %1 = load i16, i16* %arrayidx "
+               "  %2 = and i16 %1, -32768 "
+               "  ret void "
+               "} ");
+
+  checkOneCase("define void @f(i8* %arrayidx) { "
+               "  %1 = load i8, i8* %arrayidx "
+               "  %2 = and i8 %1, -128 "
+               "  ret void "
+               "} ");
+}
+
 }  // end anonymous namespace
 }  // end namespace llvm
Index: llvm/lib/Analysis/ScalarEvolutionExpander.cpp
===================================================================
--- llvm/lib/Analysis/ScalarEvolutionExpander.cpp
+++ llvm/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -840,9 +840,13 @@
       if (match(W, m_Power2(RHS))) {
         // Canonicalize Prod*(1<<C) to Prod<<C.
         assert(!Ty->isVectorTy() && "vector types are not SCEVable");
+        auto NWFlags = S->getNoWrapFlags();
+        // clear nsw flag if shl will produce poison value.
+        if (RHS->logBase2() == RHS->getBitWidth() - 1)
+          NWFlags = ScalarEvolution::clearFlags(NWFlags, SCEV::FlagNSW);
         Prod = InsertBinop(Instruction::Shl, Prod,
-                           ConstantInt::get(Ty, RHS->logBase2()),
-                           S->getNoWrapFlags(), /*IsSafeToHoist*/ true);
+                           ConstantInt::get(Ty, RHS->logBase2()), NWFlags,
+                           /*IsSafeToHoist*/ true);
       } else {
         Prod = InsertBinop(Instruction::Mul, Prod, W, S->getNoWrapFlags(),
                            /*IsSafeToHoist*/ true);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D64122.207720.patch
Type: text/x-patch
Size: 2898 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190703/bb129358/attachment.bin>


More information about the llvm-commits mailing list