Skip to content

Commit 3f72627

Browse files
fhahnllvmbot
authored andcommitted
[ConstraintElim] Make sure min/max intrinsic results are not poison.
The result of umin may be poison and in that case the added constraints are not be valid in contexts where poison doesn't cause UB. Only queue facts for min/max intrinsics if the result is guaranteed to not be poison. This could be improved in the future, by only adding the fact when solving conditions using the result value. Fixes #78621. (cherry picked from commit 3d91d96)
1 parent 30a5358 commit 3f72627

File tree

3 files changed

+13
-4
lines changed

3 files changed

+13
-4
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -1061,11 +1061,16 @@ void State::addInfoFor(BasicBlock &BB) {
10611061
FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
10621062
break;
10631063
// Enqueue the intrinsics to add extra info.
1064-
case Intrinsic::abs:
10651064
case Intrinsic::umin:
10661065
case Intrinsic::umax:
10671066
case Intrinsic::smin:
10681067
case Intrinsic::smax:
1068+
// TODO: Check if it is possible to instead only added the min/max facts
1069+
// when simplifying uses of the min/max intrinsics.
1070+
if (!isGuaranteedNotToBePoison(&I))
1071+
break;
1072+
[[fallthrough]];
1073+
case Intrinsic::abs:
10691074
WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
10701075
break;
10711076
}

llvm/test/Transforms/ConstraintElimination/minmax.ll

+3-1
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,9 @@ define i1 @smin_branchless(i32 %x, i32 %y) {
306306
; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
307307
; CHECK-NEXT: entry:
308308
; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y]])
309-
; CHECK-NEXT: [[RET:%.*]] = xor i1 true, false
309+
; CHECK-NEXT: [[CMP1:%.*]] = icmp sle i32 [[MIN]], [[X]]
310+
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[MIN]], [[X]]
311+
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP1]], [[CMP2]]
310312
; CHECK-NEXT: ret i1 [[RET]]
311313
;
312314
entry:

llvm/test/Transforms/ConstraintElimination/umin-result-may-be-poison.ll

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
define i1 @umin_not_used(i32 %arg) {
77
; CHECK-LABEL: define i1 @umin_not_used(
88
; CHECK-SAME: i32 [[ARG:%.*]]) {
9+
; CHECK-NEXT: [[ICMP:%.*]] = icmp slt i32 [[ARG]], 0
910
; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[ARG]], 3
1011
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL]], i32 80)
1112
; CHECK-NEXT: [[CMP2:%.*]] = shl nuw nsw i32 [[ARG]], 3
12-
; CHECK-NEXT: ret i1 false
13+
; CHECK-NEXT: ret i1 [[ICMP]]
1314
;
1415
%icmp = icmp slt i32 %arg, 0
1516
%shl = shl nuw nsw i32 %arg, 3
@@ -38,12 +39,13 @@ define i1 @umin_poison_is_UB_via_call(i32 %arg) {
3839
define i1 @umin_poison_call_before_UB(i32 %arg) {
3940
; CHECK-LABEL: define i1 @umin_poison_call_before_UB(
4041
; CHECK-SAME: i32 [[ARG:%.*]]) {
42+
; CHECK-NEXT: [[ICMP:%.*]] = icmp slt i32 [[ARG]], 0
4143
; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[ARG]], 3
4244
; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL]], i32 80)
4345
; CHECK-NEXT: call void @fn()
4446
; CHECK-NEXT: call void @noundef(i32 noundef [[MIN]])
4547
; CHECK-NEXT: [[CMP2:%.*]] = shl nuw nsw i32 [[ARG]], 3
46-
; CHECK-NEXT: ret i1 false
48+
; CHECK-NEXT: ret i1 [[ICMP]]
4749
;
4850
%icmp = icmp slt i32 %arg, 0
4951
%shl = shl nuw nsw i32 %arg, 3

0 commit comments

Comments
 (0)