From 7f790f9a39e3178957ca965e97503eeda4c5ce23 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 16 Oct 2023 12:03:49 +0200 Subject: [PATCH] [ConstraintElim] Don't decompose values wider than 64 bits (#68803) Our coefficients are 64-bits, so adding/multiplying them can wrap in 64-bits even if there would be no wrapping the full bit width. The alternative would be to check for overflows during all adds/muls in decomposition. I assume that we don't particularly care about handling wide integers here, so I've opted to bail out. Fixes https://github.com/llvm/llvm-project/issues/68751. (cherry picked from commit 1d43096e16ff7288c7feac1ae81fd4f745ce10bb) --- .../Transforms/Scalar/ConstraintElimination.cpp | 16 +++++++++++++--- .../ConstraintElimination/large-constant-ints.ll | 7 ++++--- .../test/Transforms/ConstraintElimination/shl.ll | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index 2b88dd08d88b66..5365bca0ab47e3 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -412,6 +412,19 @@ static Decomposition decompose(Value *V, return ResA; }; + Type *Ty = V->getType()->getScalarType(); + if (Ty->isPointerTy() && !IsSigned) { + if (auto *GEP = dyn_cast(V)) + return decomposeGEP(*GEP, Preconditions, IsSigned, DL); + return V; + } + + // Don't handle integers > 64 bit. Our coefficients are 64-bit large, so + // coefficient add/mul may wrap, while the operation in the full bit width + // would not. + if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64) + return V; + // Decompose \p V used with a signed predicate. if (IsSigned) { if (auto *CI = dyn_cast(V)) { @@ -439,9 +452,6 @@ static Decomposition decompose(Value *V, return int64_t(CI->getZExtValue()); } - if (auto *GEP = dyn_cast(V)) - return decomposeGEP(*GEP, Preconditions, IsSigned, DL); - Value *Op0; bool IsKnownNonNegative = false; if (match(V, m_ZExt(m_Value(Op0)))) { diff --git a/llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll b/llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll index 91ab42ee701b41..7f1b9f78d4c690 100644 --- a/llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll +++ b/llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll @@ -96,6 +96,7 @@ else: ret i1 false } +; TODO: This could be folded. define i1 @sub_decomp_i80(i80 %a) { ; CHECK-LABEL: @sub_decomp_i80( ; CHECK-NEXT: entry: @@ -105,7 +106,7 @@ define i1 @sub_decomp_i80(i80 %a) { ; CHECK: then: ; CHECK-NEXT: [[SUB_1:%.*]] = sub nuw i80 [[A]], 1973801615886922022913 ; CHECK-NEXT: [[C_1:%.*]] = icmp ult i80 [[SUB_1]], 1346612317380797267967 -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 [[C_1]] ; CHECK: else: ; CHECK-NEXT: ret i1 false ; @@ -423,12 +424,12 @@ entry: ret i1 %res } -; FIXME: This is a miscompile. define i1 @pr68751(i128 %arg) { ; CHECK-LABEL: @pr68751( ; CHECK-NEXT: [[SHL1:%.*]] = shl nuw nsw i128 [[ARG:%.*]], 32 ; CHECK-NEXT: [[SHL2:%.*]] = shl nuw nsw i128 [[SHL1]], 32 -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i128 [[SHL2]], 0 +; CHECK-NEXT: ret i1 [[CMP]] ; %shl1 = shl nuw nsw i128 %arg, 32 %shl2 = shl nuw nsw i128 %shl1, 32 diff --git a/llvm/test/Transforms/ConstraintElimination/shl.ll b/llvm/test/Transforms/ConstraintElimination/shl.ll index 6d196f77da1c9b..c15072fa8520c0 100644 --- a/llvm/test/Transforms/ConstraintElimination/shl.ll +++ b/llvm/test/Transforms/ConstraintElimination/shl.ll @@ -1281,7 +1281,7 @@ define i1 @shl_55() { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SHL_UB:%.*]] = shl nuw nsw i256 1, 55 ; CHECK-NEXT: [[SHL_CMP:%.*]] = icmp uge i256 [[SHL_UB]], 1 -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 [[SHL_CMP]] ; entry: %shl.ub = shl nuw nsw i256 1, 55