Skip to content

Commit daf897d

Browse files
committed
[IR] Check for SignedMin/-1 division in canTrap() (PR56038)
In addition to division by zero, signed division also traps for SignedMin / -1. This was handled in isSafeToSpeculativelyExecute(), but not in Constant::canTrap().
1 parent 610139d commit daf897d

File tree

2 files changed

+90
-5
lines changed

2 files changed

+90
-5
lines changed

llvm/lib/IR/Constants.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -587,14 +587,19 @@ static bool canTrapImpl(const Constant *C,
587587
switch (CE->getOpcode()) {
588588
default:
589589
return false;
590-
case Instruction::UDiv:
591590
case Instruction::SDiv:
592-
case Instruction::URem:
593591
case Instruction::SRem:
594-
// Div and rem can trap if the RHS is not known to be non-zero.
595-
if (!isa<ConstantInt>(CE->getOperand(1)) ||CE->getOperand(1)->isNullValue())
592+
// Signed div/rem can trap for SignedMin / -1.
593+
if (!CE->getOperand(0)->isNotMinSignedValue() &&
594+
(!isa<ConstantInt>(CE->getOperand(1)) ||
595+
CE->getOperand(1)->isAllOnesValue()))
596596
return true;
597-
return false;
597+
LLVM_FALLTHROUGH;
598+
case Instruction::UDiv:
599+
case Instruction::URem:
600+
// Div and rem can trap if the RHS is not known to be non-zero.
601+
return !isa<ConstantInt>(CE->getOperand(1)) ||
602+
CE->getOperand(1)->isNullValue();
598603
}
599604
}
600605

llvm/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,83 @@ end:
8989
%phi = phi <1 x i64> [ zeroinitializer, %entry ], [ <i64 srem (i64 1, i64 ptrtoint (i32* @g to i64))>, %if ]
9090
ret <1 x i64> %phi
9191
}
92+
93+
define i64 @pt56038_sdiv_minus_one(i1 %c) {
94+
; CHECK-LABEL: @pt56038_sdiv_minus_one(
95+
; CHECK-NEXT: entry:
96+
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[END:%.*]]
97+
; CHECK: if:
98+
; CHECK-NEXT: br label [[END]]
99+
; CHECK: end:
100+
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ sdiv (i64 ptrtoint (i32* @g to i64), i64 -1), [[IF]] ], [ 0, [[ENTRY:%.*]] ]
101+
; CHECK-NEXT: ret i64 [[PHI]]
102+
;
103+
entry:
104+
br i1 %c, label %if, label %end
105+
106+
if:
107+
br label %end
108+
109+
end:
110+
%phi = phi i64 [ sdiv (i64 ptrtoint (i32* @g to i64), i64 -1), %if ], [ 0, %entry ]
111+
ret i64 %phi
112+
}
113+
114+
define i64 @pt56038_srem_not_minus_one(i1 %c) {
115+
; CHECK-LABEL: @pt56038_srem_not_minus_one(
116+
; CHECK-NEXT: entry:
117+
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i64 sdiv (i64 ptrtoint (i32* @g to i64), i64 -2), i64 0
118+
; CHECK-NEXT: ret i64 [[SPEC_SELECT]]
119+
;
120+
entry:
121+
br i1 %c, label %if, label %end
122+
123+
if:
124+
br label %end
125+
126+
end:
127+
%phi = phi i64 [ sdiv (i64 ptrtoint (i32* @g to i64), i64 -2), %if ], [ 0, %entry ]
128+
ret i64 %phi
129+
}
130+
131+
define i64 @pt56038_sdiv_signed_min(i1 %c) {
132+
; CHECK-LABEL: @pt56038_sdiv_signed_min(
133+
; CHECK-NEXT: entry:
134+
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[END:%.*]]
135+
; CHECK: if:
136+
; CHECK-NEXT: br label [[END]]
137+
; CHECK: end:
138+
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ sdiv (i64 -9223372036854775808, i64 ptrtoint (i32* @g to i64)), [[IF]] ], [ 0, [[ENTRY:%.*]] ]
139+
; CHECK-NEXT: ret i64 [[PHI]]
140+
;
141+
entry:
142+
br i1 %c, label %if, label %end
143+
144+
if:
145+
br label %end
146+
147+
end:
148+
%phi = phi i64 [ sdiv (i64 -9223372036854775808, i64 ptrtoint (i32* @g to i64)), %if ], [ 0, %entry ]
149+
ret i64 %phi
150+
}
151+
152+
define i64 @pt56038_sdiv_not_signed_min_but_maybe_div_by_zero(i1 %c) {
153+
; CHECK-LABEL: @pt56038_sdiv_not_signed_min_but_maybe_div_by_zero(
154+
; CHECK-NEXT: entry:
155+
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[END:%.*]]
156+
; CHECK: if:
157+
; CHECK-NEXT: br label [[END]]
158+
; CHECK: end:
159+
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ sdiv (i64 -9223372036854775807, i64 ptrtoint (i32* @g to i64)), [[IF]] ], [ 0, [[ENTRY:%.*]] ]
160+
; CHECK-NEXT: ret i64 [[PHI]]
161+
;
162+
entry:
163+
br i1 %c, label %if, label %end
164+
165+
if:
166+
br label %end
167+
168+
end:
169+
%phi = phi i64 [ sdiv (i64 -9223372036854775807, i64 ptrtoint (i32* @g to i64)), %if ], [ 0, %entry ]
170+
ret i64 %phi
171+
}

0 commit comments

Comments
 (0)