From 611a02cce509d304ebf66054b7816f1e0b5a792c Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 30 Jun 2021 09:45:50 +0100 Subject: [PATCH] [ConstantRanges] Use APInt for constant case for urem/srem. Currently UREM & SREM on constant ranges produces overly pessimistic results for single element constant ranges. Delegate to APInt's implementation if both operands are single element constant ranges. We already do something similar for other binary operators, like binary AND. Fixes PR49731. Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D105115 --- llvm/lib/IR/ConstantRange.cpp | 18 ++++++++++++ .../SCCP/binaryops-range-special-cases.ll | 28 ++++++------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index b38599fa7d98..0649776dbc22 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1221,6 +1221,15 @@ ConstantRange ConstantRange::urem(const ConstantRange &RHS) const { if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isNullValue()) return getEmpty(); + if (const APInt *RHSInt = RHS.getSingleElement()) { + // UREM by null is UB. + if (RHSInt->isNullValue()) + return getEmpty(); + // Use APInt's implementation of UREM for single element ranges. + if (const APInt *LHSInt = getSingleElement()) + return {LHSInt->urem(*RHSInt)}; + } + // L % R for L < R is L. if (getUnsignedMax().ult(RHS.getUnsignedMin())) return *this; @@ -1234,6 +1243,15 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const { if (isEmptySet() || RHS.isEmptySet()) return getEmpty(); + if (const APInt *RHSInt = RHS.getSingleElement()) { + // SREM by null is UB. + if (RHSInt->isNullValue()) + return getEmpty(); + // Use APInt's implementation of SREM for single element ranges. + if (const APInt *LHSInt = getSingleElement()) + return {LHSInt->srem(*RHSInt)}; + } + ConstantRange AbsRHS = RHS.abs(); APInt MinAbsRHS = AbsRHS.getUnsignedMin(); APInt MaxAbsRHS = AbsRHS.getUnsignedMax(); diff --git a/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll b/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll index ad6d1e452a6a..ad4ab37dfc60 100644 --- a/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll +++ b/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll @@ -98,16 +98,10 @@ bb3: define void @urem_cmp_constants() { ; CHECK-LABEL: @urem_cmp_constants( -; CHECK-NEXT: [[UREM_1:%.*]] = urem i16 12704, 12704 -; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[UREM_1]], 0 -; CHECK-NEXT: call void @use(i1 [[C_1]]) -; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[UREM_1]], 1 -; CHECK-NEXT: call void @use(i1 [[C_2]]) -; CHECK-NEXT: [[UREM_2:%.*]] = urem i16 12704, 3 -; CHECK-NEXT: [[C_3:%.*]] = icmp eq i16 [[UREM_2]], 2 -; CHECK-NEXT: call void @use(i1 [[C_3]]) -; CHECK-NEXT: [[C_4:%.*]] = icmp eq i16 [[UREM_2]], 1 -; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[UREM_3:%.*]] = urem i16 12704, 0 ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i16 [[UREM_3]], 1 ; CHECK-NEXT: call void @use(i1 [[C_5]]) @@ -132,16 +126,10 @@ define void @urem_cmp_constants() { define void @srem_cmp_constants() { ; CHECK-LABEL: @srem_cmp_constants( -; CHECK-NEXT: [[SREM_1:%.*]] = srem i16 12704, 12704 -; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[SREM_1]], 0 -; CHECK-NEXT: call void @use(i1 [[C_1]]) -; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[SREM_1]], 1 -; CHECK-NEXT: call void @use(i1 [[C_2]]) -; CHECK-NEXT: [[SREM_2:%.*]] = srem i16 12704, 3 -; CHECK-NEXT: [[C_3:%.*]] = icmp eq i16 [[SREM_2]], 2 -; CHECK-NEXT: call void @use(i1 [[C_3]]) -; CHECK-NEXT: [[C_4:%.*]] = icmp eq i16 [[SREM_2]], 1 -; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[SREM_3:%.*]] = srem i16 12704, 0 ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i16 [[SREM_3]], 1 ; CHECK-NEXT: call void @use(i1 [[C_5]])