[llvm] 611a02c - [ConstantRanges] Use APInt for constant case for urem/srem.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 30 03:21:33 PDT 2021
Author: Florian Hahn
Date: 2021-06-30T11:18:20+01:00
New Revision: 611a02cce509d304ebf66054b7816f1e0b5a792c
URL: https://github.com/llvm/llvm-project/commit/611a02cce509d304ebf66054b7816f1e0b5a792c
DIFF: https://github.com/llvm/llvm-project/commit/611a02cce509d304ebf66054b7816f1e0b5a792c.diff
LOG: [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
Added:
Modified:
llvm/lib/IR/ConstantRange.cpp
llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll
Removed:
################################################################################
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]])
More information about the llvm-commits
mailing list