From c2ee7c5700708b15bf4b9da45765acac2b4d0636 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 26 Feb 2024 05:34:34 +0800 Subject: [PATCH 1/2] [GVN] Add pre-commit tests. NFC. --- llvm/test/Transforms/GVN/pr82884.ll | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 llvm/test/Transforms/GVN/pr82884.ll diff --git a/llvm/test/Transforms/GVN/pr82884.ll b/llvm/test/Transforms/GVN/pr82884.ll new file mode 100644 index 0000000000000..ea80028bf9237 --- /dev/null +++ b/llvm/test/Transforms/GVN/pr82884.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=gvn < %s | FileCheck %s + +; Make sure nsw/nuw flags are dropped. + +define i32 @pr82884(i32 %x) { +; CHECK-LABEL: define i32 @pr82884( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X]], [[X]] +; CHECK-NEXT: call void @use(i32 [[MUL]]) +; CHECK-NEXT: [[MUL2:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[X]], i32 [[X]]) +; CHECK-NEXT: ret i32 [[MUL]] +; + %mul = mul nsw nuw i32 %x, %x + call void @use(i32 %mul) + %mul2 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 %x) + %ret = extractvalue { i32, i1 } %mul2, 0 + ret i32 %ret +} + +declare void @use(i32) From b2e9a6f1b363eb26d4a8937db440f8129c034eb8 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 26 Feb 2024 05:37:35 +0800 Subject: [PATCH 2/2] [GVN] Drop nsw/nuw flags when replacing the result of a with.overflow intrinsic with a overflowing binary operator --- llvm/lib/Transforms/Utils/Local.cpp | 8 +++++++- llvm/test/Transforms/GVN/pr82884.ll | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 1373f5f7f4490..075eeb5b19fd2 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -3369,11 +3369,17 @@ void llvm::patchReplacementInstruction(Instruction *I, Value *Repl) { // Patch the replacement so that it is not more restrictive than the value // being replaced. + WithOverflowInst *UnusedWO; + // When replacing the result of a llvm.*.with.overflow intrinsic with a + // overflowing binary operator, nuw/nsw flags may no longer hold. + if (isa(ReplInst) && + match(I, m_ExtractValue<0>(m_WithOverflowInst(UnusedWO)))) + ReplInst->dropPoisonGeneratingFlags(); // Note that if 'I' is a load being replaced by some operation, // for example, by an arithmetic operation, then andIRFlags() // would just erase all math flags from the original arithmetic // operation, which is clearly not wanted and not needed. - if (!isa(I)) + else if (!isa(I)) ReplInst->andIRFlags(I); // FIXME: If both the original and replacement value are part of the diff --git a/llvm/test/Transforms/GVN/pr82884.ll b/llvm/test/Transforms/GVN/pr82884.ll index ea80028bf9237..71abafda60d93 100644 --- a/llvm/test/Transforms/GVN/pr82884.ll +++ b/llvm/test/Transforms/GVN/pr82884.ll @@ -6,7 +6,7 @@ define i32 @pr82884(i32 %x) { ; CHECK-LABEL: define i32 @pr82884( ; CHECK-SAME: i32 [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X]], [[X]] +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X]], [[X]] ; CHECK-NEXT: call void @use(i32 [[MUL]]) ; CHECK-NEXT: [[MUL2:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[X]], i32 [[X]]) ; CHECK-NEXT: ret i32 [[MUL]]