[llvm] 0a4d3ea - [LVI] Check for non-speculatable instructions

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 13 07:10:21 PST 2023


Author: Nikita Popov
Date: 2023-01-13T16:10:12+01:00
New Revision: 0a4d3eae335c1d4dc5bd9a440af4b66ccb9d0084

URL: https://github.com/llvm/llvm-project/commit/0a4d3eae335c1d4dc5bd9a440af4b66ccb9d0084
DIFF: https://github.com/llvm/llvm-project/commit/0a4d3eae335c1d4dc5bd9a440af4b66ccb9d0084.diff

LOG: [LVI] Check for non-speculatable instructions

When constraining an operand based on a condition at a (potentially
transitive) use site, make sure we don't skip over non-speculatable
instructions. While the result is only used under the condition,
the non-speculatable instruction may have a side-effect or UB.

Demonstrating this issue requires raising the limit on the walk,
so do that.

Added: 
    

Modified: 
    llvm/lib/Analysis/LazyValueInfo.cpp
    llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index d49e18a8cea18..f1587cecf9fbd 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -1660,7 +1660,7 @@ ConstantRange LazyValueInfo::getConstantRangeAtUse(const Use &U,
   // position where V can be constrained by a select or branch condition.
   const Use *CurrU = &U;
   // TODO: Increase limit?
-  const unsigned MaxUsesToInspect = 2;
+  const unsigned MaxUsesToInspect = 3;
   for (unsigned I = 0; I < MaxUsesToInspect; ++I) {
     std::optional<ValueLatticeElement> CondVal;
     auto *CurrI = cast<Instruction>(CurrU->getUser());
@@ -1673,6 +1673,11 @@ ConstantRange LazyValueInfo::getConstantRangeAtUse(const Use &U,
       // TODO: Use non-local query?
       CondVal =
           getEdgeValueLocal(V, PHI->getIncomingBlock(*CurrU), PHI->getParent());
+    } else if (!isSafeToSpeculativelyExecute(CurrI)) {
+      // Stop walking if we hit a non-speculatable instruction. Even if the
+      // result is only used under a specific condition, executing the
+      // instruction itself may cause side effects or UB already.
+      break;
     }
     if (CondVal && CondVal->isConstantRange())
       CR = CR.intersectWith(CondVal->getConstantRange());

diff  --git a/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll b/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll
index fb1a03c1aa444..58d71b46ab180 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll
@@ -74,12 +74,10 @@ define i16 @sel_true_cond_extra_use(i16 %x) {
   ret i16 %sel
 }
 
-; TODO: We could handle this case by raising the limit on the number of
-; instructions we look through.
 define i16 @sel_true_cond_chain_speculatable(i16 %x) {
 ; CHECK-LABEL: @sel_true_cond_chain_speculatable(
-; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1)
-; CHECK-NEXT:    [[EXTRA:%.*]] = mul i16 [[SUB]], 3
+; CHECK-NEXT:    [[SUB1:%.*]] = add nuw i16 [[X:%.*]], 1
+; CHECK-NEXT:    [[EXTRA:%.*]] = mul i16 [[SUB1]], 3
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[X]], -1
 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[EXTRA]], i16 42
 ; CHECK-NEXT:    ret i16 [[SEL]]
@@ -106,6 +104,8 @@ define i16 @sel_true_cond_chain_non_speculatable(i16 %x) {
   ret i16 %sel
 }
 
+; TODO: We could handle this case by raising the limit on the number of
+; instructions we look through.
 define i16 @sel_true_cond_longer_chain(i16 %x) {
 ; CHECK-LABEL: @sel_true_cond_longer_chain(
 ; CHECK-NEXT:    [[SUB:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[X:%.*]], i16 1)


        


More information about the llvm-commits mailing list