From c934ce7ceb8807824f9ed10f69c76d2b30e2908d 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 --- lib/IR/ConstantRange.cpp | 18 ++++++++++++ .../SCCP/binaryops-range-special-cases.ll | 28 ++++++------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/lib/IR/ConstantRange.cpp b/lib/IR/ConstantRange.cpp index b38599fa7d9..0649776dbc2 100644 --- a/lib/IR/ConstantRange.cpp +++ b/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/test/Transforms/SCCP/binaryops-range-special-cases.ll b/test/Transforms/SCCP/binaryops-range-special-cases.ll index ad6d1e452a6..ad4ab37dfc6 100644 --- a/test/Transforms/SCCP/binaryops-range-special-cases.ll +++ b/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]])