Skip to content

Commit 3aea3d2

Browse files
dtcxzywtstellar
authored andcommitted
[GVN] Drop nsw/nuw flags when replacing the result of a with.overflow intrinsic with a overflowing binary operator (#82935)
Alive2: https://alive2.llvm.org/ce/z/gyL7mn Fixes #82884. (cherry picked from commit 892b4be)
1 parent 9d51bd1 commit 3aea3d2

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3369,11 +3369,17 @@ void llvm::patchReplacementInstruction(Instruction *I, Value *Repl) {
33693369

33703370
// Patch the replacement so that it is not more restrictive than the value
33713371
// being replaced.
3372+
WithOverflowInst *UnusedWO;
3373+
// When replacing the result of a llvm.*.with.overflow intrinsic with a
3374+
// overflowing binary operator, nuw/nsw flags may no longer hold.
3375+
if (isa<OverflowingBinaryOperator>(ReplInst) &&
3376+
match(I, m_ExtractValue<0>(m_WithOverflowInst(UnusedWO))))
3377+
ReplInst->dropPoisonGeneratingFlags();
33723378
// Note that if 'I' is a load being replaced by some operation,
33733379
// for example, by an arithmetic operation, then andIRFlags()
33743380
// would just erase all math flags from the original arithmetic
33753381
// operation, which is clearly not wanted and not needed.
3376-
if (!isa<LoadInst>(I))
3382+
else if (!isa<LoadInst>(I))
33773383
ReplInst->andIRFlags(I);
33783384

33793385
// FIXME: If both the original and replacement value are part of the

llvm/test/Transforms/GVN/pr82884.ll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt -S -passes=gvn < %s | FileCheck %s
3+
4+
; Make sure nsw/nuw flags are dropped.
5+
6+
define i32 @pr82884(i32 %x) {
7+
; CHECK-LABEL: define i32 @pr82884(
8+
; CHECK-SAME: i32 [[X:%.*]]) {
9+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X]], [[X]]
10+
; CHECK-NEXT: call void @use(i32 [[MUL]])
11+
; CHECK-NEXT: [[MUL2:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[X]], i32 [[X]])
12+
; CHECK-NEXT: ret i32 [[MUL]]
13+
;
14+
%mul = mul nsw nuw i32 %x, %x
15+
call void @use(i32 %mul)
16+
%mul2 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 %x)
17+
%ret = extractvalue { i32, i1 } %mul2, 0
18+
ret i32 %ret
19+
}
20+
21+
declare void @use(i32)

0 commit comments

Comments
 (0)