Skip to content

Commit 9ee7d71

Browse files
committed
[ConstantFolding] fold integer min/max intrinsics
If both operands are undef, return undef. If one operand is undef, clamp to limit constant.
1 parent 9f95895 commit 9ee7d71

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,10 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
14361436
case Intrinsic::launder_invariant_group:
14371437
case Intrinsic::strip_invariant_group:
14381438
case Intrinsic::masked_load:
1439+
case Intrinsic::smax:
1440+
case Intrinsic::smin:
1441+
case Intrinsic::umax:
1442+
case Intrinsic::umin:
14391443
case Intrinsic::sadd_with_overflow:
14401444
case Intrinsic::uadd_with_overflow:
14411445
case Intrinsic::ssub_with_overflow:
@@ -2386,8 +2390,37 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
23862390
!getConstIntOrUndef(Operands[1], C1))
23872391
return nullptr;
23882392

2393+
unsigned BitWidth = Ty->getScalarSizeInBits();
23892394
switch (IntrinsicID) {
23902395
default: break;
2396+
case Intrinsic::smax:
2397+
if (!C0 && !C1)
2398+
return UndefValue::get(Ty);
2399+
if (!C0 || !C1)
2400+
return ConstantInt::get(Ty, APInt::getSignedMaxValue(BitWidth));
2401+
return ConstantInt::get(Ty, C0->sgt(*C1) ? *C0 : *C1);
2402+
2403+
case Intrinsic::smin:
2404+
if (!C0 && !C1)
2405+
return UndefValue::get(Ty);
2406+
if (!C0 || !C1)
2407+
return ConstantInt::get(Ty, APInt::getSignedMinValue(BitWidth));
2408+
return ConstantInt::get(Ty, C0->slt(*C1) ? *C0 : *C1);
2409+
2410+
case Intrinsic::umax:
2411+
if (!C0 && !C1)
2412+
return UndefValue::get(Ty);
2413+
if (!C0 || !C1)
2414+
return ConstantInt::get(Ty, APInt::getMaxValue(BitWidth));
2415+
return ConstantInt::get(Ty, C0->ugt(*C1) ? *C0 : *C1);
2416+
2417+
case Intrinsic::umin:
2418+
if (!C0 && !C1)
2419+
return UndefValue::get(Ty);
2420+
if (!C0 || !C1)
2421+
return ConstantInt::get(Ty, APInt::getMinValue(BitWidth));
2422+
return ConstantInt::get(Ty, C0->ult(*C1) ? *C0 : *C1);
2423+
23912424
case Intrinsic::usub_with_overflow:
23922425
case Intrinsic::ssub_with_overflow:
23932426
case Intrinsic::uadd_with_overflow:

llvm/test/Analysis/ConstantFolding/min-max.ll

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,71 +139,63 @@ define <4 x float> @maximum_float_zeros_vec() {
139139

140140
define i8 @smax() {
141141
; CHECK-LABEL: @smax(
142-
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 -128, i8 -127)
143-
; CHECK-NEXT: ret i8 [[R]]
142+
; CHECK-NEXT: ret i8 -127
144143
;
145144
%r = call i8 @llvm.smax.i8(i8 128, i8 129)
146145
ret i8 %r
147146
}
148147

149148
define <5 x i8> @smax_vec() {
150149
; CHECK-LABEL: @smax_vec(
151-
; CHECK-NEXT: [[R:%.*]] = call <5 x i8> @llvm.smax.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 127>)
152-
; CHECK-NEXT: ret <5 x i8> [[R]]
150+
; CHECK-NEXT: ret <5 x i8> <i8 undef, i8 127, i8 127, i8 42, i8 127>
153151
;
154152
%r = call <5 x i8> @llvm.smax.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 127>)
155153
ret <5 x i8> %r
156154
}
157155

158156
define i8 @smin() {
159157
; CHECK-LABEL: @smin(
160-
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 -128, i8 127)
161-
; CHECK-NEXT: ret i8 [[R]]
158+
; CHECK-NEXT: ret i8 -128
162159
;
163160
%r = call i8 @llvm.smin.i8(i8 128, i8 127)
164161
ret i8 %r
165162
}
166163

167164
define <5 x i8> @smin_vec() {
168165
; CHECK-LABEL: @smin_vec(
169-
; CHECK-NEXT: [[R:%.*]] = call <5 x i8> @llvm.smin.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 -127>)
170-
; CHECK-NEXT: ret <5 x i8> [[R]]
166+
; CHECK-NEXT: ret <5 x i8> <i8 undef, i8 -128, i8 -128, i8 42, i8 -127>
171167
;
172168
%r = call <5 x i8> @llvm.smin.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 129>)
173169
ret <5 x i8> %r
174170
}
175171

176172
define i8 @umax() {
177173
; CHECK-LABEL: @umax(
178-
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umax.i8(i8 -128, i8 127)
179-
; CHECK-NEXT: ret i8 [[R]]
174+
; CHECK-NEXT: ret i8 -128
180175
;
181176
%r = call i8 @llvm.umax.i8(i8 128, i8 127)
182177
ret i8 %r
183178
}
184179

185180
define <5 x i8> @umax_vec() {
186181
; CHECK-LABEL: @umax_vec(
187-
; CHECK-NEXT: [[R:%.*]] = call <5 x i8> @llvm.umax.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 -128>)
188-
; CHECK-NEXT: ret <5 x i8> [[R]]
182+
; CHECK-NEXT: ret <5 x i8> <i8 undef, i8 -1, i8 -1, i8 42, i8 -128>
189183
;
190184
%r = call <5 x i8> @llvm.umax.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 128>)
191185
ret <5 x i8> %r
192186
}
193187

194188
define i8 @umin() {
195189
; CHECK-LABEL: @umin(
196-
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 -128, i8 127)
197-
; CHECK-NEXT: ret i8 [[R]]
190+
; CHECK-NEXT: ret i8 127
198191
;
199192
%r = call i8 @llvm.umin.i8(i8 128, i8 127)
200193
ret i8 %r
201194
}
202195

203196
define <5 x i8> @umin_vec() {
204197
; CHECK-LABEL: @umin_vec(
205-
; CHECK-NEXT: [[R:%.*]] = call <5 x i8> @llvm.umin.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 -128>)
206-
; CHECK-NEXT: ret <5 x i8> [[R]]
198+
; CHECK-NEXT: ret <5 x i8> <i8 undef, i8 0, i8 0, i8 42, i8 42>
207199
;
208200
%r = call <5 x i8> @llvm.umin.v5i8(<5 x i8> <i8 undef, i8 undef, i8 1, i8 42, i8 42>, <5 x i8> <i8 undef, i8 1, i8 undef, i8 42, i8 128>)
209201
ret <5 x i8> %r

0 commit comments

Comments
 (0)