diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1221,6 +1221,15 @@ 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 @@ 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 --- a/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll +++ b/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll @@ -98,16 +98,10 @@ 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 @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]])