diff --git a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
--- a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
+++ b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
@@ -11,6 +11,9 @@
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/Matchers.h"
 #include "llvm/ADT/APSInt.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "value-bounds-op-interface"
 
 using namespace mlir;
 using presburger::BoundType;
@@ -61,8 +64,14 @@
   LogicalResult status = cstr.addBound(
       type, pos,
       AffineMap::get(cstr.getNumDimVars(), cstr.getNumSymbolVars(), expr));
-  (void)status;
-  assert(succeeded(status) && "failed to add bound to constraint system");
+  if (failed(status)) {
+    // Non-pure (e.g., semi-affine) expressions are not yet supported by
+    // FlatLinearConstraints. However, we can just ignore such failures here.
+    // Even without this bound, there may be enough information in the
+    // constraint system to compute the requested bound. In case this bound is
+    // actually needed, `computeBound` will return `failure`.
+    LLVM_DEBUG(llvm::dbgs() << "Failed to add bound: " << expr << "\n");
+  }
 }
 
 AffineExpr ValueBoundsConstraintSet::getExpr(Value value,
diff --git a/mlir/test/Dialect/Arith/value-bounds-op-interface-impl.mlir b/mlir/test/Dialect/Arith/value-bounds-op-interface-impl.mlir
--- a/mlir/test/Dialect/Arith/value-bounds-op-interface-impl.mlir
+++ b/mlir/test/Dialect/Arith/value-bounds-op-interface-impl.mlir
@@ -1,5 +1,5 @@
 // RUN: mlir-opt %s -test-affine-reify-value-bounds -verify-diagnostics \
-// RUN:     -split-input-file | FileCheck %s
+// RUN:     -verify-diagnostics -split-input-file | FileCheck %s
 
 // CHECK: #[[$map:.*]] = affine_map<()[s0] -> (s0 + 5)>
 // CHECK-LABEL: func @arith_addi(
@@ -43,6 +43,16 @@
 
 // -----
 
+func.func @arith_muli_non_pure(%a: index, %b: index) -> index {
+  %0 = arith.muli %a, %b : index
+  // Semi-affine expressions (such as "symbol * symbol") are not supported.
+  // expected-error @below{{could not reify bound}}
+  %1 = "test.reify_bound"(%0) : (index) -> (index)
+  return %1 : index
+}
+
+// -----
+
 // CHECK-LABEL: func @arith_const()
 //       CHECK:   %[[c5:.*]] = arith.constant 5 : index
 //       CHECK:   %[[c5:.*]] = arith.constant 5 : index