Skip to content

Commit 8b22bb8

Browse files
authored
[DivRemPairs] Do not freeze poisons that can't be undef (llvm#92627)
Per comments in DivRemPairs, the rewrite from ```llvm %div = div %X, %Y %rem = rem %X, %Y ``` to ```llvm %div = div %X, %Y %.mul = mul %div, %Y %rem = sub %X, %mul ``` is unsound when %X or %Y are undef. However, it is known to be sound if %X or %Y are poison but can't be undef, since both the pre- and post-rewrite %rem are `poison`. Additionally, proofs: https://alive2.llvm.org/ce/z/xtNQ8j A comment in the pass listed a TODO for changing a usage of isGuaranteedNotToBeUndefOrPoison() in the pass to something that only detects undef. Such a function has been implemented since the time that TODO was written, but has not been used. Therefore, this commit updates DivRemPairs to use isGuaranteedNotToBeUndef() instead.
1 parent 02f1a99 commit 8b22bb8

File tree

2 files changed

+17
-30
lines changed

2 files changed

+17
-30
lines changed

llvm/lib/Transforms/Scalar/DivRemPairs.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,15 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
381381
// %mul = mul %div, 1 // %mul = undef
382382
// %rem = sub %x, %mul // %rem = undef - undef = undef
383383
// If X is not frozen, %rem becomes undef after transformation.
384-
// TODO: We need a undef-specific checking function in ValueTracking
385-
if (!isGuaranteedNotToBeUndefOrPoison(X, nullptr, DivInst, &DT)) {
384+
if (!isGuaranteedNotToBeUndef(X, nullptr, DivInst, &DT)) {
386385
auto *FrX =
387386
new FreezeInst(X, X->getName() + ".frozen", DivInst->getIterator());
388387
DivInst->setOperand(0, FrX);
389388
Sub->setOperand(0, FrX);
390389
}
391390
// Same for Y. If X = 1 and Y = (undef | 1), %rem in src is either 1 or 0,
392391
// but %rem in tgt can be one of many integer values.
393-
if (!isGuaranteedNotToBeUndefOrPoison(Y, nullptr, DivInst, &DT)) {
392+
if (!isGuaranteedNotToBeUndef(Y, nullptr, DivInst, &DT)) {
394393
auto *FrY =
395394
new FreezeInst(Y, Y->getName() + ".frozen", DivInst->getIterator());
396395
DivInst->setOperand(1, FrY);

llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,14 @@ define i32 @no_freezes(ptr %p, i32 noundef %x, i32 noundef %y) {
3333
ret i32 %rem
3434
}
3535

36-
; FIXME: There should be no need to `freeze` x2 and y2 since they have defined
37-
; but potentially poison values.
3836
define i32 @poison_does_not_freeze(ptr %p, i32 noundef %x, i32 noundef %y) {
3937
; CHECK-LABEL: define i32 @poison_does_not_freeze(
4038
; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) {
4139
; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i32 [[X]], 5
4240
; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1
43-
; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze i32 [[X2]]
44-
; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]]
45-
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X2_FROZEN]], [[Y2_FROZEN]]
46-
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]]
47-
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2_FROZEN]], [[TMP1]]
41+
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X2]], [[Y2]]
42+
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]]
43+
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2]], [[TMP1]]
4844
; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4
4945
; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]]
5046
;
@@ -61,11 +57,9 @@ define i32 @poison_does_not_freeze_signed(ptr %p, i32 noundef %x, i32 noundef %y
6157
; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) {
6258
; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i32 [[X]], 5
6359
; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1
64-
; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze i32 [[X2]]
65-
; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]]
66-
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X2_FROZEN]], [[Y2_FROZEN]]
67-
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]]
68-
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2_FROZEN]], [[TMP1]]
60+
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X2]], [[Y2]]
61+
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]]
62+
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2]], [[TMP1]]
6963
; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4
7064
; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]]
7165
;
@@ -82,11 +76,9 @@ define <4 x i8> @poison_does_not_freeze_vector(ptr %p, <4 x i8> noundef %x, <4 x
8276
; CHECK-SAME: ptr [[P:%.*]], <4 x i8> noundef [[X:%.*]], <4 x i8> noundef [[Y:%.*]]) {
8377
; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw <4 x i8> [[X]], <i8 5, i8 5, i8 5, i8 5>
8478
; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw <4 x i8> [[Y]], <i8 1, i8 1, i8 1, i8 1>
85-
; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze <4 x i8> [[X2]]
86-
; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze <4 x i8> [[Y2]]
87-
; CHECK-NEXT: [[DIV:%.*]] = udiv <4 x i8> [[X2_FROZEN]], [[Y2_FROZEN]]
88-
; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i8> [[DIV]], [[Y2_FROZEN]]
89-
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub <4 x i8> [[X2_FROZEN]], [[TMP1]]
79+
; CHECK-NEXT: [[DIV:%.*]] = udiv <4 x i8> [[X2]], [[Y2]]
80+
; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i8> [[DIV]], [[Y2]]
81+
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub <4 x i8> [[X2]], [[TMP1]]
9082
; CHECK-NEXT: store <4 x i8> [[DIV]], ptr [[P]], align 4
9183
; CHECK-NEXT: ret <4 x i8> [[REM_DECOMPOSED]]
9284
;
@@ -103,11 +95,9 @@ define i32 @explicit_poison_does_not_freeze(ptr %p, i32 noundef %y) {
10395
; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[Y:%.*]]) {
10496
; CHECK-NEXT: [[X:%.*]] = add i32 poison, 1
10597
; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1
106-
; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X]]
107-
; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]]
108-
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X_FROZEN]], [[Y2_FROZEN]]
109-
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]]
110-
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]]
98+
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[Y2]]
99+
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]]
100+
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X]], [[TMP1]]
111101
; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4
112102
; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]]
113103
;
@@ -124,11 +114,9 @@ define i32 @explicit_poison_does_not_freeze_signed(ptr %p, i32 noundef %y) {
124114
; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[Y:%.*]]) {
125115
; CHECK-NEXT: [[X:%.*]] = add i32 poison, 1
126116
; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1
127-
; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X]]
128-
; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]]
129-
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X_FROZEN]], [[Y2_FROZEN]]
130-
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]]
131-
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]]
117+
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y2]]
118+
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]]
119+
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X]], [[TMP1]]
132120
; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4
133121
; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]]
134122
;

0 commit comments

Comments
 (0)