Skip to content

Commit 6c667ab

Browse files
committed
Recommit "[ValueTracking] Use knownbits interface for determining if div/rem are safe to speculate" (2nd Try)
Add `poison` checks that where missing. Reviewed By: nikic
1 parent 6cdc229 commit 6c667ab

File tree

2 files changed

+98
-28
lines changed

2 files changed

+98
-28
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6033,31 +6033,34 @@ bool llvm::isSafeToSpeculativelyExecuteWithOpcode(
60336033
default:
60346034
return true;
60356035
case Instruction::UDiv:
6036-
case Instruction::URem: {
6037-
// x / y is undefined if y == 0.
6038-
const APInt *V;
6039-
if (match(Inst->getOperand(1), m_APInt(V)))
6040-
return *V != 0;
6041-
return false;
6042-
}
6036+
case Instruction::URem:
60436037
case Instruction::SDiv:
60446038
case Instruction::SRem: {
6045-
// x / y is undefined if y == 0 or x == INT_MIN and y == -1
6046-
const APInt *Numerator, *Denominator;
6047-
if (!match(Inst->getOperand(1), m_APInt(Denominator)))
6048-
return false;
6049-
// We cannot hoist this division if the denominator is 0.
6050-
if (*Denominator == 0)
6039+
// x / y is undefined if y == 0 or y is poison.
6040+
const DataLayout &DL = Inst->getModule()->getDataLayout();
6041+
if (!isGuaranteedNotToBePoison(Inst->getOperand(1), AC, CtxI, DT) ||
6042+
!isKnownNonZero(Inst->getOperand(1), DL, /*Depth*/ 0, AC, CtxI, DT))
60516043
return false;
6044+
6045+
// Unsigned case only needs to avoid denominator == 0 or poison.
6046+
if (Opcode == Instruction::UDiv || Opcode == Instruction::URem)
6047+
return true;
6048+
6049+
// x s/ y is also undefined if x == INT_MIN and y == -1
6050+
KnownBits KnownDenominator =
6051+
computeKnownBits(Inst->getOperand(1), DL, /*Depth*/ 0, AC, CtxI, DT);
6052+
60526053
// It's safe to hoist if the denominator is not 0 or -1.
6053-
if (!Denominator->isAllOnes())
6054+
if (!KnownDenominator.Zero.isZero())
60546055
return true;
6055-
// At this point we know that the denominator is -1. It is safe to hoist as
6056-
// long we know that the numerator is not INT_MIN.
6057-
if (match(Inst->getOperand(0), m_APInt(Numerator)))
6058-
return !Numerator->isMinSignedValue();
6059-
// The numerator *might* be MinSignedValue.
6060-
return false;
6056+
6057+
// At this point denominator may be -1. It is safe to hoist as
6058+
// long we know that the numerator is neither poison nor INT_MIN.
6059+
if (!isGuaranteedNotToBePoison(Inst->getOperand(0), AC, CtxI, DT))
6060+
return false;
6061+
KnownBits KnownNumerator =
6062+
computeKnownBits(Inst->getOperand(0), DL, /*Depth*/ 0, AC, CtxI, DT);
6063+
return !KnownNumerator.getSignedMinValue().isMinSignedValue();
60616064
}
60626065
case Instruction::Load: {
60636066
const LoadInst *LI = dyn_cast<LoadInst>(Inst);

llvm/test/Transforms/LICM/speculate-div.ll

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
declare void @maythrow()
55
declare void @use(i16)
66

7-
define void @sdiv_not_ok(i16 %n, i16 %xx) {
7+
define void @sdiv_not_ok(i16 %n, i16 noundef %xx) {
88
; CHECK-LABEL: @sdiv_not_ok(
99
; CHECK-NEXT: entry:
1010
; CHECK-NEXT: [[X:%.*]] = or i16 [[XX:%.*]], 1
@@ -25,7 +25,7 @@ loop:
2525
br label %loop
2626
}
2727

28-
define void @srem_not_ok2(i16 %nn, i16 %x) {
28+
define void @srem_not_ok2(i16 %nn, i16 noundef %x) {
2929
; CHECK-LABEL: @srem_not_ok2(
3030
; CHECK-NEXT: entry:
3131
; CHECK-NEXT: [[N:%.*]] = and i16 [[NN:%.*]], 1323
@@ -46,15 +46,15 @@ loop:
4646
br label %loop
4747
}
4848

49-
define void @sdiv_ok(i16 %n, i16 %xx) {
49+
define void @sdiv_ok(i16 %n, i16 noundef %xx) {
5050
; CHECK-LABEL: @sdiv_ok(
5151
; CHECK-NEXT: entry:
5252
; CHECK-NEXT: [[XO:%.*]] = or i16 [[XX:%.*]], 1
5353
; CHECK-NEXT: [[X:%.*]] = and i16 [[XO]], 123
54+
; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[N:%.*]], [[X]]
5455
; CHECK-NEXT: br label [[LOOP:%.*]]
5556
; CHECK: loop:
5657
; CHECK-NEXT: call void @maythrow()
57-
; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[N:%.*]], [[X]]
5858
; CHECK-NEXT: call void @use(i16 [[DIV]])
5959
; CHECK-NEXT: br label [[LOOP]]
6060
;
@@ -69,15 +69,15 @@ loop:
6969
br label %loop
7070
}
7171

72-
define void @srem_ok2(i16 %nn, i16 %xx) {
72+
define void @srem_ok2(i16 noundef %nn, i16 noundef %xx) {
7373
; CHECK-LABEL: @srem_ok2(
7474
; CHECK-NEXT: entry:
7575
; CHECK-NEXT: [[N:%.*]] = and i16 [[NN:%.*]], 123
7676
; CHECK-NEXT: [[X:%.*]] = or i16 [[XX:%.*]], 1
77+
; CHECK-NEXT: [[DIV:%.*]] = srem i16 [[N]], [[X]]
7778
; CHECK-NEXT: br label [[LOOP:%.*]]
7879
; CHECK: loop:
7980
; CHECK-NEXT: call void @maythrow()
80-
; CHECK-NEXT: [[DIV:%.*]] = srem i16 [[N]], [[X]]
8181
; CHECK-NEXT: call void @use(i16 [[DIV]])
8282
; CHECK-NEXT: br label [[LOOP]]
8383
;
@@ -92,7 +92,53 @@ loop:
9292
br label %loop
9393
}
9494

95-
define void @udiv_not_ok(i16 %n, i16 %xx) {
95+
define void @sdiv_not_ok3_maybe_poison_denum(i16 noundef %nn, i16 %xx) {
96+
; CHECK-LABEL: @sdiv_not_ok3_maybe_poison_denum(
97+
; CHECK-NEXT: entry:
98+
; CHECK-NEXT: [[N:%.*]] = and i16 [[NN:%.*]], 123
99+
; CHECK-NEXT: [[X:%.*]] = or i16 [[XX:%.*]], 1
100+
; CHECK-NEXT: br label [[LOOP:%.*]]
101+
; CHECK: loop:
102+
; CHECK-NEXT: call void @maythrow()
103+
; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[N]], [[X]]
104+
; CHECK-NEXT: call void @use(i16 [[DIV]])
105+
; CHECK-NEXT: br label [[LOOP]]
106+
;
107+
entry:
108+
%n = and i16 %nn, 123
109+
%x = or i16 %xx, 1
110+
br label %loop
111+
loop:
112+
call void @maythrow()
113+
%div = sdiv i16 %n, %x
114+
call void @use(i16 %div)
115+
br label %loop
116+
}
117+
118+
define void @sdiv_not_ok3_maybe_poison_num(i16 %nn, i16 noundef %xx) {
119+
; CHECK-LABEL: @sdiv_not_ok3_maybe_poison_num(
120+
; CHECK-NEXT: entry:
121+
; CHECK-NEXT: [[N:%.*]] = and i16 [[NN:%.*]], 123
122+
; CHECK-NEXT: [[X:%.*]] = or i16 [[XX:%.*]], 1
123+
; CHECK-NEXT: br label [[LOOP:%.*]]
124+
; CHECK: loop:
125+
; CHECK-NEXT: call void @maythrow()
126+
; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[N]], [[X]]
127+
; CHECK-NEXT: call void @use(i16 [[DIV]])
128+
; CHECK-NEXT: br label [[LOOP]]
129+
;
130+
entry:
131+
%n = and i16 %nn, 123
132+
%x = or i16 %xx, 1
133+
br label %loop
134+
loop:
135+
call void @maythrow()
136+
%div = sdiv i16 %n, %x
137+
call void @use(i16 %div)
138+
br label %loop
139+
}
140+
141+
define void @udiv_not_ok(i16 %n, i16 noundef %xx) {
96142
; CHECK-LABEL: @udiv_not_ok(
97143
; CHECK-NEXT: entry:
98144
; CHECK-NEXT: [[X:%.*]] = xor i16 [[XX:%.*]], 1
@@ -113,10 +159,31 @@ loop:
113159
br label %loop
114160
}
115161

116-
define void @udiv_ok(i16 %n, i16 %xx) {
162+
define void @udiv_ok(i16 %n, i16 noundef %xx) {
117163
; CHECK-LABEL: @udiv_ok(
118164
; CHECK-NEXT: entry:
119165
; CHECK-NEXT: [[X:%.*]] = or i16 [[XX:%.*]], 1
166+
; CHECK-NEXT: [[DIV:%.*]] = udiv i16 [[N:%.*]], [[X]]
167+
; CHECK-NEXT: br label [[LOOP:%.*]]
168+
; CHECK: loop:
169+
; CHECK-NEXT: call void @maythrow()
170+
; CHECK-NEXT: call void @use(i16 [[DIV]])
171+
; CHECK-NEXT: br label [[LOOP]]
172+
;
173+
entry:
174+
%x = or i16 %xx, 1
175+
br label %loop
176+
loop:
177+
call void @maythrow()
178+
%div = udiv i16 %n, %x
179+
call void @use(i16 %div)
180+
br label %loop
181+
}
182+
183+
define void @urem_not_ok_maybe_poison(i16 %n, i16 %xx) {
184+
; CHECK-LABEL: @urem_not_ok_maybe_poison(
185+
; CHECK-NEXT: entry:
186+
; CHECK-NEXT: [[X:%.*]] = or i16 [[XX:%.*]], 1
120187
; CHECK-NEXT: br label [[LOOP:%.*]]
121188
; CHECK: loop:
122189
; CHECK-NEXT: call void @maythrow()

0 commit comments

Comments
 (0)