[llvm-branch-commits] [clang] 7d8d30d - [Clang][NFC] Added testcase from #49549
Author: Dávid Bolvanský Date: 2022-01-31T23:43:36+01:00 New Revision: 7d8d30d6d3ddb37230a519bf4ee8144a547e4195 URL: https://github.com/llvm/llvm-project/commit/7d8d30d6d3ddb37230a519bf4ee8144a547e4195 DIFF: https://github.com/llvm/llvm-project/commit/7d8d30d6d3ddb37230a519bf4ee8144a547e4195.diff LOG: [Clang][NFC] Added testcase from #49549 The issue is fixed in trunk, so add testcase to avoid regression in the future. Added: Modified: clang/test/SemaCXX/attr-likelihood.cpp Removed: diff --git a/clang/test/SemaCXX/attr-likelihood.cpp b/clang/test/SemaCXX/attr-likelihood.cpp index f7503fed49b93..642d62fa89826 100644 --- a/clang/test/SemaCXX/attr-likelihood.cpp +++ b/clang/test/SemaCXX/attr-likelihood.cpp @@ -159,4 +159,18 @@ constexpr int constexpr_function() { [[likely]] return 0; } static_assert(constexpr_function() == 0); + +constexpr double pow(double x, long long n) noexcept { +if (n > 0) [[likely]] +return x * pow(x, n - 1); +else [[unlikely]] +return 1; +} +constexpr long long fact(long long n) noexcept { +if (n > 1) [[likely]] +return n * fact(n - 1); +else [[unlikely]] +return 1; +} + #endif ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 7a61357 - [AlwaysInliner] Enable call site inlining to make flatten attribute working again (#53360)
Author: Dávid Bolvanský Date: 2022-01-25T22:51:51+01:00 New Revision: 7a61357ea2c3b737ce338452aee058033119fa28 URL: https://github.com/llvm/llvm-project/commit/7a61357ea2c3b737ce338452aee058033119fa28 DIFF: https://github.com/llvm/llvm-project/commit/7a61357ea2c3b737ce338452aee058033119fa28.diff LOG: [AlwaysInliner] Enable call site inlining to make flatten attribute working again (#53360) Problem: Migration to new PM broke flatten attribute. This is one use case why LLVM should support inlining call-site with alwaysinline. The flatten attribute is nowdays broken, so we should either land patch like this one or remove everything related to flatten attribute from Clang. Second use case is something like "per call site inlining intrinsics" to control inlining even more; mentioned in https://lists.llvm.org/pipermail/cfe-dev/2018-September/059232.html Fixes https://github.com/llvm/llvm-project/issues/53360 Reviewed By: aeubanks Differential Revision: https://reviews.llvm.org/D117965 Added: Modified: clang/test/CodeGen/flatten.c clang/test/CodeGenCXX/flatten.cpp llvm/lib/Transforms/IPO/AlwaysInliner.cpp llvm/test/Transforms/Coroutines/coro-retcon-once-private.ll llvm/test/Transforms/Inline/always-inline.ll Removed: diff --git a/clang/test/CodeGen/flatten.c b/clang/test/CodeGen/flatten.c index 287d4f2a46b65..4e762223de486 100644 --- a/clang/test/CodeGen/flatten.c +++ b/clang/test/CodeGen/flatten.c @@ -1,9 +1,3 @@ -// UNSUPPORTED: experimental-new-pass-manager -// Currently, diff erent code seems to be intentionally generated under the new -// PM since we alwaysinline functions and not callsites under new PM. -// Under new PM, f() will not be inlined from g() since f is not marked as -// alwaysinline. - // RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o - | FileCheck %s void f(void) {} diff --git a/clang/test/CodeGenCXX/flatten.cpp b/clang/test/CodeGenCXX/flatten.cpp index 7a6484591aaa0..e988d6d726dd7 100644 --- a/clang/test/CodeGenCXX/flatten.cpp +++ b/clang/test/CodeGenCXX/flatten.cpp @@ -1,7 +1,3 @@ -// UNSUPPORTED: experimental-new-pass-manager -// See the comment for CodeGen/flatten.c on why this is unsupported with the new -// PM. - // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++11 %s -emit-llvm -o - | FileCheck %s void f(void) {} diff --git a/llvm/lib/Transforms/IPO/AlwaysInliner.cpp b/llvm/lib/Transforms/IPO/AlwaysInliner.cpp index 7acc9b266ad82..8f20f59b5e4d7 100644 --- a/llvm/lib/Transforms/IPO/AlwaysInliner.cpp +++ b/llvm/lib/Transforms/IPO/AlwaysInliner.cpp @@ -54,13 +54,13 @@ PreservedAnalyses AlwaysInlinerPass::run(Module , if (F.isPresplitCoroutine()) continue; -if (!F.isDeclaration() && F.hasFnAttribute(Attribute::AlwaysInline) && -isInlineViable(F).isSuccess()) { +if (!F.isDeclaration() && isInlineViable(F).isSuccess()) { Calls.clear(); for (User *U : F.users()) if (auto *CB = dyn_cast(U)) - if (CB->getCalledFunction() == ) + if (CB->getCalledFunction() == && + CB->hasFnAttr(Attribute::AlwaysInline)) Calls.insert(CB); for (CallBase *CB : Calls) { diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-once-private.ll b/llvm/test/Transforms/Coroutines/coro-retcon-once-private.ll index d805d7549231d..5d62747180233 100644 --- a/llvm/test/Transforms/Coroutines/coro-retcon-once-private.ll +++ b/llvm/test/Transforms/Coroutines/coro-retcon-once-private.ll @@ -3,9 +3,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.12.0" -; CHECK: define internal { i8*, i32 } @f(i8* %buffer, i32* %array) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; CHECK-NOT: define {{.*}} @f(i8* %buffer, i32* %array) define internal {i8*, i32} @f(i8* %buffer, i32* %array) { entry: diff --git a/llvm/test/Transforms/Inline/always-inline.ll b/llvm/test/Transforms/Inline/always-inline.ll index 0fcf956199c46..8eb3d020f6634 100644 --- a/llvm/test/Transforms/Inline/always-inline.ll +++ b/llvm/test/Transforms/Inline/always-inline.ll @@ -1,14 +1,11 @@ -; RUN: opt < %s -inline-threshold=0 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL +; RUN: opt < %s -inline-threshold=0 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK ; ; Ensure the threshold has no impact on these decisions. -; RUN: opt < %s -inline-threshold=2000 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL -; RUN: opt < %s -inline-threshold=-2000 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL +; RUN: opt < %s -inline-threshold=2000 -always-inline -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK +; RUN: opt < %s -inline-threshold=-2000
[llvm-branch-commits] [llvm] bb3f169 - [BuildLibcalls, Attrs] Support more variants of C++'s new, add attributes for C++'s delete
Author: Dávid Bolvanský Date: 2021-01-21T00:12:37+01:00 New Revision: bb3f169b59e1c8bd7fd70097532220bbd11e9967 URL: https://github.com/llvm/llvm-project/commit/bb3f169b59e1c8bd7fd70097532220bbd11e9967 DIFF: https://github.com/llvm/llvm-project/commit/bb3f169b59e1c8bd7fd70097532220bbd11e9967.diff LOG: [BuildLibcalls, Attrs] Support more variants of C++'s new, add attributes for C++'s delete Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D95095 Added: Modified: llvm/lib/Transforms/Utils/BuildLibCalls.cpp llvm/test/Transforms/InferFunctionAttrs/annotate.ll Removed: diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index 857c3d915e8c..a14c30071399 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1001,10 +1001,52 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); return Changed; + case LibFunc_ZdlPvRKSt9nothrow_t: // delete(void*, nothrow) + case LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t: // delete(void*, align_val_t, nothrow) + case LibFunc_ZdaPvRKSt9nothrow_t: // delete[](void*, nothrow) + case LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t: // delete[](void*, align_val_t, nothrow) +Changed |= setDoesNotThrow(F); +LLVM_FALLTHROUGH; + case LibFunc_ZdlPv: // delete(void*) + case LibFunc_ZdlPvj: // delete(void*, unsigned int) + case LibFunc_ZdlPvm: // delete(void*, unsigned long) + case LibFunc_ZdaPv: // delete[](void*) + case LibFunc_ZdaPvj: // delete[](void*, unsigned int) + case LibFunc_ZdaPvm: // delete[](void*, unsigned long) + case LibFunc_ZdlPvSt11align_val_t: // delete(void*, align_val_t) + case LibFunc_ZdlPvjSt11align_val_t: // delete(void*, unsigned int, align_val_t) + case LibFunc_ZdlPvmSt11align_val_t: // delete(void*, unsigned long, align_val_t) + case LibFunc_ZdaPvSt11align_val_t: // delete[](void*, align_val_t) + case LibFunc_ZdaPvjSt11align_val_t: // delete[](void*, unsigned int, align_val_t) + case LibFunc_ZdaPvmSt11align_val_t: // delete[](void*, unsigned long, align_val_t); +Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F); +Changed |= setArgsNoUndef(F); +Changed |= setWillReturn(F); +Changed |= setDoesNotCapture(F, 0); +return Changed; + case LibFunc_ZnwjRKSt9nothrow_t: // new(unsigned int, nothrow) + case LibFunc_ZnwmRKSt9nothrow_t: // new(unsigned long, nothrow) + case LibFunc_ZnajRKSt9nothrow_t: // new[](unsigned int, nothrow) + case LibFunc_ZnamRKSt9nothrow_t: // new[](unsigned long, nothrow) + case LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t: // new(unsigned int, align_val_t, nothrow) + case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t: // new(unsigned long, align_val_t, nothrow) + case LibFunc_ZnajSt11align_val_tRKSt9nothrow_t: // new[](unsigned int, align_val_t, nothrow) + case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t: // new[](unsigned long, align_val_t, nothrow) +// Nothrow operator new may return null pointer +Changed |= setDoesNotThrow(F); +Changed |= setOnlyAccessesInaccessibleMemory(F); +Changed |= setRetNoUndef(F); +Changed |= setRetDoesNotAlias(F); +Changed |= setWillReturn(F); +return Changed; case LibFunc_Znwj: // new(unsigned int) case LibFunc_Znwm: // new(unsigned long) case LibFunc_Znaj: // new[](unsigned int) case LibFunc_Znam: // new[](unsigned long) + case LibFunc_ZnwjSt11align_val_t: // new(unsigned int, align_val_t) + case LibFunc_ZnwmSt11align_val_t: // new(unsigned long, align_val_t) + case LibFunc_ZnajSt11align_val_t: // new[](unsigned int, align_val_t) + case LibFunc_ZnamSt11align_val_t: // new[](unsigned long, align_val_t) case LibFunc_msvc_new_int: // new(unsigned int) case LibFunc_msvc_new_longlong: // new(unsigned long long) case LibFunc_msvc_new_array_int: // new[](unsigned int) diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll index 0af18151d6f6..a847db7eb550 100644 --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -9,6 +9,30 @@ declare i8* @_Znwj(i64 ) ; CHECK: declare noalias noundef nonnull i8* @_Znwj(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN:#[0-9]+]] declare i8* @_Znwm(i64) ; CHECK: declare noalias noundef nonnull i8* @_Znwm(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] +declare i8* @_Znaj(i64) +; CHECK: declare noalias noundef nonnull i8* @_Znaj(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] +declare i8* @_Znam(i64) +; CHECK: declare noalias noundef nonnull i8* @_Znam(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] + + +%"struct.std::nothrow_t" = type { i8 } +declare i8* @_ZnwmRKSt9nothrow_t(i64, %"struct.std::nothrow_t"*) +;
[llvm-branch-commits] [llvm] 16d6e85 - [BuildLibcalls] Mark some libcalls with inaccessiblememonly and inaccessiblemem_or_argmemonly
Author: Dávid Bolvanský Date: 2021-01-20T19:45:23+01:00 New Revision: 16d6e8527189298c75bf5690c771e8ab6dc3628d URL: https://github.com/llvm/llvm-project/commit/16d6e8527189298c75bf5690c771e8ab6dc3628d DIFF: https://github.com/llvm/llvm-project/commit/16d6e8527189298c75bf5690c771e8ab6dc3628d.diff LOG: [BuildLibcalls] Mark some libcalls with inaccessiblememonly and inaccessiblemem_or_argmemonly Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D94850 Added: Modified: llvm/lib/Transforms/Utils/BuildLibCalls.cpp llvm/test/Transforms/InferFunctionAttrs/annotate.ll Removed: diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index d2ffb99274e3..857c3d915e8c 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -31,8 +31,12 @@ using namespace llvm; //- Infer Attributes -// STATISTIC(NumReadNone, "Number of functions inferred as readnone"); +STATISTIC(NumInaccessibleMemOnly, + "Number of functions inferred as inaccessiblememonly"); STATISTIC(NumReadOnly, "Number of functions inferred as readonly"); STATISTIC(NumArgMemOnly, "Number of functions inferred as argmemonly"); +STATISTIC(NumInaccessibleMemOrArgMemOnly, + "Number of functions inferred as inaccessiblemem_or_argmemonly"); STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind"); STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture"); STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly"); @@ -52,6 +56,14 @@ static bool setDoesNotAccessMemory(Function ) { return true; } +static bool setOnlyAccessesInaccessibleMemory(Function ) { + if (F.onlyAccessesInaccessibleMemory()) +return false; + F.setOnlyAccessesInaccessibleMemory(); + ++NumInaccessibleMemOnly; + return true; +} + static bool setOnlyReadsMemory(Function ) { if (F.onlyReadsMemory()) return false; @@ -68,6 +80,14 @@ static bool setOnlyAccessesArgMemory(Function ) { return true; } +static bool setOnlyAccessesInaccessibleMemOrArgMem(Function ) { + if (F.onlyAccessesInaccessibleMemOrArgMem()) +return false; + F.setOnlyAccessesInaccessibleMemOrArgMem(); + ++NumInaccessibleMemOrArgMemOnly; + return true; +} + static bool setDoesNotThrow(Function ) { if (F.doesNotThrow()) return false; @@ -315,6 +335,7 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { return Changed; case LibFunc_strdup: case LibFunc_strndup: +Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); @@ -370,6 +391,7 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { Changed |= setOnlyReadsMemory(F, 0); return Changed; case LibFunc_malloc: +Changed |= setOnlyAccessesInaccessibleMemory(F); Changed |= setRetNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); @@ -432,6 +454,9 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { Changed |= setDoesNotThrow(F); return Changed; case LibFunc_memalign: +Changed |= setOnlyAccessesInaccessibleMemory(F); +Changed |= setRetNoUndef(F); +Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); return Changed; @@ -448,6 +473,7 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { Changed |= setDoesNotCapture(F, 0); return Changed; case LibFunc_realloc: +Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F); Changed |= setRetNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); @@ -498,6 +524,7 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { Changed |= setOnlyReadsMemory(F, 1); return Changed; case LibFunc_aligned_alloc: +Changed |= setOnlyAccessesInaccessibleMemory(F); Changed |= setRetNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); @@ -528,6 +555,7 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { Changed |= setOnlyWritesMemory(F, 0); return Changed; case LibFunc_calloc: +Changed |= setOnlyAccessesInaccessibleMemory(F); Changed |= setRetNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); @@ -584,6 +612,7 @@ bool llvm::inferLibFuncAttributes(Function , const TargetLibraryInfo ) { Changed |= setDoesNotCapture(F, 0); return Changed; case LibFunc_free: +Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F); Changed |= setArgsNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setWillReturn(F); @@
[llvm-branch-commits] [llvm] ed39621 - [InstCombine] Transform abs pattern using multiplication to abs intrinsic (PR45691)
Author: Dávid Bolvanský Date: 2021-01-17T17:06:14+01:00 New Revision: ed396212da41feed9bffb8cc1ca6518ab031a3c7 URL: https://github.com/llvm/llvm-project/commit/ed396212da41feed9bffb8cc1ca6518ab031a3c7 DIFF: https://github.com/llvm/llvm-project/commit/ed396212da41feed9bffb8cc1ca6518ab031a3c7.diff LOG: [InstCombine] Transform abs pattern using multiplication to abs intrinsic (PR45691) ``` unsigned r(int v) { return (1 | -(v < 0)) * v; } `r` is equivalent to `abs(v)`. ``` ``` define <4 x i8> @src(<4 x i8> %0) { %1: %2 = ashr <4 x i8> %0, { 31, undef, 31, 31 } %3 = or <4 x i8> %2, { 1, 1, 1, undef } %4 = mul nsw <4 x i8> %3, %0 ret <4 x i8> %4 } => define <4 x i8> @tgt(<4 x i8> %0) { %1: %2 = icmp slt <4 x i8> %0, { 0, 0, 0, 0 } %3 = sub nsw <4 x i8> { 0, 0, 0, 0 }, %0 %4 = select <4 x i1> %2, <4 x i8> %3, <4 x i8> %0 ret <4 x i8> %4 } Transformation seems to be correct! ``` Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D94874 Added: Modified: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll Removed: diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 2da7415b908b..4b485a0ad85e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -153,8 +153,10 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator ) { if (Value *V = SimplifyUsingDistributiveLaws(I)) return replaceInstUsesWith(I, V); - // X * -1 == 0 - X Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + unsigned BitWidth = I.getType()->getScalarSizeInBits(); + + // X * -1 == 0 - X if (match(Op1, m_AllOnes())) { BinaryOperator *BO = BinaryOperator::CreateNeg(Op0, I.getName()); if (I.hasNoSignedWrap()) @@ -360,6 +362,19 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator ) { if (match(Op1, m_LShr(m_Value(X), m_APInt(C))) && *C == C->getBitWidth() - 1) return BinaryOperator::CreateAnd(Builder.CreateAShr(X, *C), Op0); + // ((ashr X, 31) | 1) * X --> abs(X) + // X * ((ashr X, 31) | 1) --> abs(X) + if (match(, m_c_BinOp(m_Or(m_AShr(m_Value(X), +m_SpecificIntAllowUndef(BitWidth - 1)), + m_One()), +m_Deferred(X { +Value *Abs = Builder.CreateBinaryIntrinsic( +Intrinsic::abs, X, +ConstantInt::getBool(I.getContext(), I.hasNoSignedWrap())); +Abs->takeName(); +return replaceInstUsesWith(I, Abs); + } + if (Instruction *Ext = narrowMathIfNoOverflow(I)) return Ext; diff --git a/llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll b/llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll index 1874378f1f1f..ab390a209340 100644 --- a/llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll +++ b/llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll @@ -6,9 +6,7 @@ define i32 @ashr_or_mul_to_abs(i32 %X) { ; CHECK-LABEL: @ashr_or_mul_to_abs( -; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 31 -; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 1 -; CHECK-NEXT:[[I2:%.*]] = mul nsw i32 [[I1]], [[X]] +; CHECK-NEXT:[[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) ; CHECK-NEXT:ret i32 [[I2]] ; %i = ashr i32 %X, 31 @@ -19,9 +17,7 @@ define i32 @ashr_or_mul_to_abs(i32 %X) { define i32 @ashr_or_mul_to_abs2(i32 %X) { ; CHECK-LABEL: @ashr_or_mul_to_abs2( -; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 31 -; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 1 -; CHECK-NEXT:[[I2:%.*]] = mul i32 [[I1]], [[X]] +; CHECK-NEXT:[[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false) ; CHECK-NEXT:ret i32 [[I2]] ; %i = ashr i32 %X, 31 @@ -30,13 +26,13 @@ define i32 @ashr_or_mul_to_abs2(i32 %X) { ret i32 %i2 } -define i32 @ashr_or_mul_to_abs3(i32 %X) { +define i32 @ashr_or_mul_to_abs3(i32 %PX) { ; CHECK-LABEL: @ashr_or_mul_to_abs3( -; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 31 -; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 1 -; CHECK-NEXT:[[I2:%.*]] = mul i32 [[I1]], [[X]] +; CHECK-NEXT:[[X:%.*]] = sdiv i32 42, [[PX:%.*]] +; CHECK-NEXT:[[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) ; CHECK-NEXT:ret i32 [[I2]] ; + %X = sdiv i32 42, %PX ; thwart complexity-based canonicalization %i = ashr i32 %X, 31 %i1 = or i32 %i, 1 %i2 = mul i32 %X, %i1 @@ -46,9 +42,7 @@ define i32 @ashr_or_mul_to_abs3(i32 %X) { define <4 x i32> @ashr_or_mul_to_abs_vec(<4 x i32> %X) { ; CHECK-LABEL: @ashr_or_mul_to_abs_vec( -; CHECK-NEXT:[[I:%.*]] = ashr <4 x i32> [[X:%.*]], -; CHECK-NEXT:[[I1:%.*]] = or <4 x i32> [[I]], -; CHECK-NEXT:[[I2:%.*]] = mul <4 x i32> [[I1]], [[X]] +; CHECK-NEXT:[[I2:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1
[llvm-branch-commits] [llvm] 469ceaf - [Tests] Add test for PR45691
Author: Dávid Bolvanský Date: 2021-01-17T17:04:49+01:00 New Revision: 469ceaf53892d26f7b68f86f1feb38fe7057815e URL: https://github.com/llvm/llvm-project/commit/469ceaf53892d26f7b68f86f1feb38fe7057815e DIFF: https://github.com/llvm/llvm-project/commit/469ceaf53892d26f7b68f86f1feb38fe7057815e.diff LOG: [Tests] Add test for PR45691 Added: llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll Modified: Removed: diff --git a/llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll b/llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll new file mode 100644 index ..1874378f1f1f --- /dev/null +++ b/llvm/test/Transforms/InstCombine/ashr-or-mul-abs.ll @@ -0,0 +1,112 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; ((ashr X, 31) | 1 ) * X --> abs(X) +; X * ((ashr X, 31) | 1 ) --> abs(X) + +define i32 @ashr_or_mul_to_abs(i32 %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs( +; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 31 +; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 1 +; CHECK-NEXT:[[I2:%.*]] = mul nsw i32 [[I1]], [[X]] +; CHECK-NEXT:ret i32 [[I2]] +; + %i = ashr i32 %X, 31 + %i1 = or i32 %i, 1 + %i2 = mul nsw i32 %i1, %X + ret i32 %i2 +} + +define i32 @ashr_or_mul_to_abs2(i32 %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs2( +; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 31 +; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 1 +; CHECK-NEXT:[[I2:%.*]] = mul i32 [[I1]], [[X]] +; CHECK-NEXT:ret i32 [[I2]] +; + %i = ashr i32 %X, 31 + %i1 = or i32 %i, 1 + %i2 = mul i32 %i1, %X + ret i32 %i2 +} + +define i32 @ashr_or_mul_to_abs3(i32 %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs3( +; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 31 +; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 1 +; CHECK-NEXT:[[I2:%.*]] = mul i32 [[I1]], [[X]] +; CHECK-NEXT:ret i32 [[I2]] +; + %i = ashr i32 %X, 31 + %i1 = or i32 %i, 1 + %i2 = mul i32 %X, %i1 + ret i32 %i2 +} + + +define <4 x i32> @ashr_or_mul_to_abs_vec(<4 x i32> %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs_vec( +; CHECK-NEXT:[[I:%.*]] = ashr <4 x i32> [[X:%.*]], +; CHECK-NEXT:[[I1:%.*]] = or <4 x i32> [[I]], +; CHECK-NEXT:[[I2:%.*]] = mul <4 x i32> [[I1]], [[X]] +; CHECK-NEXT:ret <4 x i32> [[I2]] +; + %i = ashr <4 x i32> %X, + %i1 = or <4 x i32> %i, + %i2 = mul <4 x i32> %i1, %X + ret <4 x i32> %i2 +} + +define <4 x i32> @ashr_or_mul_to_abs_vec2(<4 x i32> %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs_vec2( +; CHECK-NEXT:[[I:%.*]] = ashr <4 x i32> [[X:%.*]], +; CHECK-NEXT:[[I1:%.*]] = or <4 x i32> [[I]], +; CHECK-NEXT:[[I2:%.*]] = mul nsw <4 x i32> [[I1]], [[X]] +; CHECK-NEXT:ret <4 x i32> [[I2]] +; + %i = ashr <4 x i32> %X, + %i1 = or <4 x i32> %i, + %i2 = mul nsw <4 x i32> %i1, %X + ret <4 x i32> %i2 +} + +define <4 x i32> @ashr_or_mul_to_abs_vec3_undef(<4 x i32> %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs_vec3_undef( +; CHECK-NEXT:[[I:%.*]] = ashr <4 x i32> [[X:%.*]], +; CHECK-NEXT:[[I1:%.*]] = or <4 x i32> [[I]], +; CHECK-NEXT:[[I2:%.*]] = mul <4 x i32> [[I1]], [[X]] +; CHECK-NEXT:ret <4 x i32> [[I2]] +; + %i = ashr <4 x i32> %X, + %i1 = or <4 x i32> %i, + %i2 = mul <4 x i32> %i1, %X + ret <4 x i32> %i2 +} + +; Negative tests + +define i32 @ashr_or_mul_to_abs_neg(i32 %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs_neg( +; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 30 +; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 1 +; CHECK-NEXT:[[I2:%.*]] = mul nsw i32 [[I1]], [[X]] +; CHECK-NEXT:ret i32 [[I2]] +; + %i = ashr i32 %X, 30 + %i1 = or i32 %i, 1 + %i2 = mul nsw i32 %i1, %X + ret i32 %i2 +} + +define i32 @ashr_or_mul_to_abs_neg2(i32 %X) { +; CHECK-LABEL: @ashr_or_mul_to_abs_neg2( +; CHECK-NEXT:[[I:%.*]] = ashr i32 [[X:%.*]], 31 +; CHECK-NEXT:[[I1:%.*]] = or i32 [[I]], 2 +; CHECK-NEXT:[[I2:%.*]] = mul nsw i32 [[I1]], [[X]] +; CHECK-NEXT:ret i32 [[I2]] +; + %i = ashr i32 %X, 31 + %i1 = or i32 %i, 2 + %i2 = mul nsw i32 %i1, %X + ret i32 %i2 +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] bfd75bd - [NFC] Removed extra text in comments
Author: Dávid Bolvanský Date: 2021-01-16T22:48:56+01:00 New Revision: bfd75bdf3fd62d4f5e7028d4122f9ffa517f2a09 URL: https://github.com/llvm/llvm-project/commit/bfd75bdf3fd62d4f5e7028d4122f9ffa517f2a09 DIFF: https://github.com/llvm/llvm-project/commit/bfd75bdf3fd62d4f5e7028d4122f9ffa517f2a09.diff LOG: [NFC] Removed extra text in comments Added: Modified: llvm/lib/Analysis/InstructionSimplify.cpp Removed: diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 6a065c46d9bf..b672798aaffc 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2236,7 +2236,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery , // Commute the 'or' operands. // (A ^ B) | (A & ~B) -> (A ^ B) - // (A ^ B) | (~B & A) -> (A ^ B)D94870 + // (A ^ B) | (~B & A) -> (A ^ B) // (B ^ A) | (A & ~B) -> (B ^ A) // (B ^ A) | (~B & A) -> (B ^ A) if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 63bedc8 - [InstSimplify] Handle commutativity for 'and' and 'outer or' for (~A & B) | ~(A | B) --> ~A
Author: Dávid Bolvanský Date: 2021-01-16T19:42:50+01:00 New Revision: 63bedc80da36cf5eb71b06b453c186e057607bf4 URL: https://github.com/llvm/llvm-project/commit/63bedc80da36cf5eb71b06b453c186e057607bf4 DIFF: https://github.com/llvm/llvm-project/commit/63bedc80da36cf5eb71b06b453c186e057607bf4.diff LOG: [InstSimplify] Handle commutativity for 'and' and 'outer or' for (~A & B) | ~(A | B) --> ~A Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D94870 Added: Modified: llvm/lib/Analysis/InstructionSimplify.cpp llvm/test/Transforms/InstSimplify/or.ll Removed: diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 73f046dcb8de..6a065c46d9bf 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2224,7 +2224,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery , if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::Or)) return V; - Value *A, *B; + Value *A, *B, *NotA; // (A & ~B) | (A ^ B) -> (A ^ B) // (~B & A) | (A ^ B) -> (A ^ B) // (A & ~B) | (B ^ A) -> (B ^ A) @@ -2236,7 +2236,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery , // Commute the 'or' operands. // (A ^ B) | (A & ~B) -> (A ^ B) - // (A ^ B) | (~B & A) -> (A ^ B) + // (A ^ B) | (~B & A) -> (A ^ B)D94870 // (B ^ A) | (A & ~B) -> (B ^ A) // (B ^ A) | (~B & A) -> (B ^ A) if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && @@ -2253,6 +2253,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery , match(Op1, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B) return Op1; + // Commute the 'or' operands. // (~A ^ B) | (A & B) -> (~A ^ B) // (~A ^ B) | (B & A) -> (~A ^ B) // (B ^ ~A) | (A & B) -> (B ^ ~A) @@ -2266,9 +2267,20 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery , // (~A & B) | ~(B | A) --> ~A // (B & ~A) | ~(A | B) --> ~A // (B & ~A) | ~(B | A) --> ~A - if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) && + if (match(Op0, m_c_And(m_CombineAnd(m_Value(NotA), m_Not(m_Value(A))), + m_Value(B))) && match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B) -return cast(Op0)->getOperand(0); +return NotA; + + // Commute the 'or' operands. + // ~(A | B) | (~A & B) --> ~A + // ~(B | A) | (~A & B) --> ~A + // ~(A | B) | (B & ~A) --> ~A + // ~(B | A) | (B & ~A) --> ~A + if (match(Op1, m_c_And(m_CombineAnd(m_Value(NotA), m_Not(m_Value(A))), + m_Value(B))) && + match(Op0, m_Not(m_c_Or(m_Specific(A), m_Specific(B) +return NotA; if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false)) return V; diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll index 68d2af4a4041..7f347193be9a 100644 --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -399,11 +399,7 @@ define i32 @and_or_not_or4_use3(i32 %A, i32 %B) { define i32 @and_or_not_or5(i32 %A, i32 %B) { ; CHECK-LABEL: @and_or_not_or5( ; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT:[[I2:%.*]] = and i32 [[B:%.*]], [[I]] -; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] -; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] -; CHECK-NEXT:ret i32 [[I5]] +; CHECK-NEXT:ret i32 [[I]] ; %i = xor i32 %A, -1 %i2 = and i32 %B, %i @@ -416,11 +412,7 @@ define i32 @and_or_not_or5(i32 %A, i32 %B) { define i32 @and_or_not_or6(i32 %A, i32 %B) { ; CHECK-LABEL: @and_or_not_or6( ; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[B:%.*]] -; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] -; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] -; CHECK-NEXT:ret i32 [[I5]] +; CHECK-NEXT:ret i32 [[I]] ; %i = xor i32 %A, -1 %i2 = and i32 %i, %B @@ -433,11 +425,7 @@ define i32 @and_or_not_or6(i32 %A, i32 %B) { define i32 @and_or_not_or7(i32 %A, i32 %B) { ; CHECK-LABEL: @and_or_not_or7( ; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT:[[I2:%.*]] = and i32 [[B:%.*]], [[I]] -; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] -; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] -; CHECK-NEXT:ret i32 [[I5]] +; CHECK-NEXT:ret i32 [[I]] ; %i = xor i32 %A, -1 %i2 = and i32 %B, %i @@ -450,11 +438,7 @@ define i32 @and_or_not_or7(i32 %A, i32 %B) { define i32 @and_or_not_or8(i32 %A, i32 %B) { ; CHECK-LABEL: @and_or_not_or8( ; CHECK-NEXT:[[I:%.*]] = xor i32 [[B:%.*]], -1 -; CHECK-NEXT:[[I2:%.*]] = and i32 [[A:%.*]], [[I]] -; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]],
[llvm-branch-commits] [llvm] 416854d - [InstSimplify] Precommit new testcases; NFC
Author: Dávid Bolvanský Date: 2021-01-16T19:11:58+01:00 New Revision: 416854d0f7cda90def07e9b4aee14505f222b0b3 URL: https://github.com/llvm/llvm-project/commit/416854d0f7cda90def07e9b4aee14505f222b0b3 DIFF: https://github.com/llvm/llvm-project/commit/416854d0f7cda90def07e9b4aee14505f222b0b3.diff LOG: [InstSimplify] Precommit new testcases; NFC Added: Modified: llvm/test/Transforms/InstSimplify/or.ll Removed: diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll index 7e7361d12395..68d2af4a4041 100644 --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -395,3 +395,71 @@ define i32 @and_or_not_or4_use3(i32 %A, i32 %B) { %i5 = or i32 %i4, %i2 ret i32 %i5 } + +define i32 @and_or_not_or5(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or5( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[B:%.*]], [[I]] +; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %B, %i + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define i32 @and_or_not_or6(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or6( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[B:%.*]] +; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %i, %B + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} + +define i32 @and_or_not_or7(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or7( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[B:%.*]], [[I]] +; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %B, %i + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} + +define i32 @and_or_not_or8(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or8( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[A:%.*]], [[I]] +; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = xor i32 %B, -1 + %i2 = and i32 %A, %i + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] bdd4dda - [InstSimplify] Update comments, remove redundant tests
Author: Dávid Bolvanský Date: 2021-01-16T16:31:23+01:00 New Revision: bdd4dda58b0de08bd3474fb8d4589a9ba9349e88 URL: https://github.com/llvm/llvm-project/commit/bdd4dda58b0de08bd3474fb8d4589a9ba9349e88 DIFF: https://github.com/llvm/llvm-project/commit/bdd4dda58b0de08bd3474fb8d4589a9ba9349e88.diff LOG: [InstSimplify] Update comments, remove redundant tests Added: Modified: llvm/lib/Analysis/InstructionSimplify.cpp llvm/test/Transforms/InstCombine/or.ll Removed: diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 6266e922f8c9..73f046dcb8de 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2264,6 +2264,8 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery , // (~A & B) | ~(A | B) --> ~A // (~A & B) | ~(B | A) --> ~A + // (B & ~A) | ~(A | B) --> ~A + // (B & ~A) | ~(B | A) --> ~A if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) && match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B) return cast(Op0)->getOperand(0); diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll index 0fc75fe082f8..22ba395ebe9f 100644 --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -1369,113 +1369,3 @@ define i32 @test5_use3(i32 %x, i32 %y) { %or1 = or i32 %xor, %neg ret i32 %or1 } - -define i32 @test6(i32 %A, i32 %B) { -; CHECK-LABEL: @test6( -; CHECK-NEXT:[[I:%.*]] = xor i32 [[B:%.*]], -1 -; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[A:%.*]] -; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] -; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] -; CHECK-NEXT:ret i32 [[I5]] -; - %i = xor i32 %B, -1 - %i2 = and i32 %i, %A - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i2, %i4 - ret i32 %i5 -} - -define i32 @test7(i32 %A, i32 %B) { -; CHECK-LABEL: @test7( -; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[B:%.*]] -; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] -; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] -; CHECK-NEXT:ret i32 [[I5]] -; - %i = xor i32 %A, -1 - %i2 = and i32 %i, %B - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i2, %i4 - ret i32 %i5 -} - -define <4 x i32> @test8_vec(<4 x i32> %A, <4 x i32> %B) { -; CHECK-LABEL: @test8_vec( -; CHECK-NEXT:[[I:%.*]] = xor <4 x i32> [[A:%.*]], -; CHECK-NEXT:[[I2:%.*]] = and <4 x i32> [[I]], [[B:%.*]] -; CHECK-NEXT:[[I3:%.*]] = or <4 x i32> [[B]], [[A]] -; CHECK-NEXT:[[I4:%.*]] = xor <4 x i32> [[I3]], -; CHECK-NEXT:[[I5:%.*]] = or <4 x i32> [[I2]], [[I4]] -; CHECK-NEXT:ret <4 x i32> [[I5]] -; - %i = xor <4 x i32> %A, - %i2 = and <4 x i32> %i, %B - %i3 = or <4 x i32> %B, %A - %i4 = xor <4 x i32> %i3, - %i5 = or <4 x i32> %i2, %i4 - ret <4 x i32> %i5 -} - -define i32 @test9_use(i32 %A, i32 %B) { -; CHECK-LABEL: @test9_use( -; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[B:%.*]] -; CHECK-NEXT:tail call void @use(i32 [[I2]]) -; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] -; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] -; CHECK-NEXT:ret i32 [[I5]] -; - %i = xor i32 %A, -1 - %i2 = and i32 %i, %B - tail call void @use(i32 %i2) - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i2, %i4 - ret i32 %i5 -} - -define i32 @test9_use2(i32 %A, i32 %B) { -; CHECK-LABEL: @test9_use2( -; CHECK-NEXT:[[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT:[[I2:%.*]] = xor i32 [[I]], -1 -; CHECK-NEXT:tail call void @use(i32 [[I2]]) -; CHECK-NEXT:[[I3:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT:[[I4:%.*]] = and i32 [[I3]], [[B]] -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] -; CHECK-NEXT:ret i32 [[I5]] -; - %i = or i32 %B, %A - %i2 = xor i32 %i, -1 - tail call void @use(i32 %i2) - %i3 = xor i32 %A, -1 - %i4 = and i32 %i3, %B - %i5 = or i32 %i4, %i2 - ret i32 %i5 -} - -define i32 @test9_use3(i32 %A, i32 %B) { -; CHECK-LABEL: @test9_use3( -; CHECK-NEXT:[[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT:[[I2:%.*]] = xor i32 [[I]], -1 -; CHECK-NEXT:tail call void @use(i32 [[I2]]) -; CHECK-NEXT:[[I3:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT:[[I4:%.*]] = and i32 [[I3]], [[B]] -; CHECK-NEXT:tail call void @use(i32 [[I4]]) -; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] -; CHECK-NEXT:ret i32 [[I5]] -; - %i = or i32 %B, %A - %i2 = xor i32 %i, -1 - tail call void @use(i32 %i2) - %i3 = xor i32 %A, -1 - %i4 = and i32 %i3, %B - tail call void @use(i32 %i4) - %i5 = or i32 %i4, %i2 - ret i32 %i5 -}
[llvm-branch-commits] [llvm] a4e2a51 - [InstSimplify] Add (~A & B) | ~(A | B) --> ~A
Author: Dávid Bolvanský Date: 2021-01-16T15:43:34+01:00 New Revision: a4e2a5145a29af678139f33e94ab3df0fc973e59 URL: https://github.com/llvm/llvm-project/commit/a4e2a5145a29af678139f33e94ab3df0fc973e59 DIFF: https://github.com/llvm/llvm-project/commit/a4e2a5145a29af678139f33e94ab3df0fc973e59.diff LOG: [InstSimplify] Add (~A & B) | ~(A | B) --> ~A Added: Modified: llvm/lib/Analysis/InstructionSimplify.cpp llvm/test/Transforms/InstSimplify/or.ll Removed: diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 2ae4228495e3..6266e922f8c9 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2262,6 +2262,12 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery , match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B) return Op0; + // (~A & B) | ~(A | B) --> ~A + // (~A & B) | ~(B | A) --> ~A + if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) && + match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B) +return cast(Op0)->getOperand(0); + if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false)) return V; diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll index e8284264c612..7e7361d12395 100644 --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -301,3 +301,97 @@ define i32 @poison(i32 %x) { %v = or i32 %x, poison ret i32 %v } + +declare void @use(i32) + +define i32 @and_or_not_or(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT:ret i32 [[I]] +; + %i = xor i32 %B, -1 + %i2 = and i32 %i, %A + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define i32 @and_or_not_or2(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or2( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT:ret i32 [[I]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %i, %B + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define <4 x i32> @and_or_not_or3_vec(<4 x i32> %A, <4 x i32> %B) { +; CHECK-LABEL: @and_or_not_or3_vec( +; CHECK-NEXT:[[I:%.*]] = xor <4 x i32> [[A:%.*]], +; CHECK-NEXT:ret <4 x i32> [[I]] +; + %i = xor <4 x i32> %A, + %i2 = and <4 x i32> %i, %B + %i3 = or <4 x i32> %B, %A + %i4 = xor <4 x i32> %i3, + %i5 = or <4 x i32> %i2, %i4 + ret <4 x i32> %i5 +} + +define i32 @and_or_not_or4_use(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or4_use( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[B:%.*]] +; CHECK-NEXT:tail call void @use(i32 [[I2]]) +; CHECK-NEXT:ret i32 [[I]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %i, %B + tail call void @use(i32 %i2) + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define i32 @and_or_not_or4_use2(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or4_use2( +; CHECK-NEXT:[[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT:[[I2:%.*]] = xor i32 [[I]], -1 +; CHECK-NEXT:tail call void @use(i32 [[I2]]) +; CHECK-NEXT:[[I3:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT:ret i32 [[I3]] +; + %i = or i32 %B, %A + %i2 = xor i32 %i, -1 + tail call void @use(i32 %i2) + %i3 = xor i32 %A, -1 + %i4 = and i32 %i3, %B + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} + +define i32 @and_or_not_or4_use3(i32 %A, i32 %B) { +; CHECK-LABEL: @and_or_not_or4_use3( +; CHECK-NEXT:[[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT:[[I2:%.*]] = xor i32 [[I]], -1 +; CHECK-NEXT:tail call void @use(i32 [[I2]]) +; CHECK-NEXT:[[I3:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT:[[I4:%.*]] = and i32 [[I3]], [[B]] +; CHECK-NEXT:tail call void @use(i32 [[I4]]) +; CHECK-NEXT:ret i32 [[I3]] +; + %i = or i32 %B, %A + %i2 = xor i32 %i, -1 + tail call void @use(i32 %i2) + %i3 = xor i32 %A, -1 + %i4 = and i32 %i3, %B + tail call void @use(i32 %i4) + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 9fc814e - [Tests] Added tests for new instcombine or simplification; NFC
Author: Dávid Bolvanský Date: 2021-01-16T15:43:33+01:00 New Revision: 9fc814ed59669d8f1d06cde5714c17fac652f2a1 URL: https://github.com/llvm/llvm-project/commit/9fc814ed59669d8f1d06cde5714c17fac652f2a1 DIFF: https://github.com/llvm/llvm-project/commit/9fc814ed59669d8f1d06cde5714c17fac652f2a1.diff LOG: [Tests] Added tests for new instcombine or simplification; NFC Added: Modified: llvm/test/Transforms/InstCombine/or.ll Removed: diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll index ff6244526563..0fc75fe082f8 100644 --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -1370,3 +1370,112 @@ define i32 @test5_use3(i32 %x, i32 %y) { ret i32 %or1 } +define i32 @test6(i32 %A, i32 %B) { +; CHECK-LABEL: @test6( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[A:%.*]] +; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = xor i32 %B, -1 + %i2 = and i32 %i, %A + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define i32 @test7(i32 %A, i32 %B) { +; CHECK-LABEL: @test7( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[B:%.*]] +; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %i, %B + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define <4 x i32> @test8_vec(<4 x i32> %A, <4 x i32> %B) { +; CHECK-LABEL: @test8_vec( +; CHECK-NEXT:[[I:%.*]] = xor <4 x i32> [[A:%.*]], +; CHECK-NEXT:[[I2:%.*]] = and <4 x i32> [[I]], [[B:%.*]] +; CHECK-NEXT:[[I3:%.*]] = or <4 x i32> [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor <4 x i32> [[I3]], +; CHECK-NEXT:[[I5:%.*]] = or <4 x i32> [[I2]], [[I4]] +; CHECK-NEXT:ret <4 x i32> [[I5]] +; + %i = xor <4 x i32> %A, + %i2 = and <4 x i32> %i, %B + %i3 = or <4 x i32> %B, %A + %i4 = xor <4 x i32> %i3, + %i5 = or <4 x i32> %i2, %i4 + ret <4 x i32> %i5 +} + +define i32 @test9_use(i32 %A, i32 %B) { +; CHECK-LABEL: @test9_use( +; CHECK-NEXT:[[I:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT:[[I2:%.*]] = and i32 [[I]], [[B:%.*]] +; CHECK-NEXT:tail call void @use(i32 [[I2]]) +; CHECK-NEXT:[[I3:%.*]] = or i32 [[B]], [[A]] +; CHECK-NEXT:[[I4:%.*]] = xor i32 [[I3]], -1 +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I2]], [[I4]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = xor i32 %A, -1 + %i2 = and i32 %i, %B + tail call void @use(i32 %i2) + %i3 = or i32 %B, %A + %i4 = xor i32 %i3, -1 + %i5 = or i32 %i2, %i4 + ret i32 %i5 +} + +define i32 @test9_use2(i32 %A, i32 %B) { +; CHECK-LABEL: @test9_use2( +; CHECK-NEXT:[[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT:[[I2:%.*]] = xor i32 [[I]], -1 +; CHECK-NEXT:tail call void @use(i32 [[I2]]) +; CHECK-NEXT:[[I3:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT:[[I4:%.*]] = and i32 [[I3]], [[B]] +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = or i32 %B, %A + %i2 = xor i32 %i, -1 + tail call void @use(i32 %i2) + %i3 = xor i32 %A, -1 + %i4 = and i32 %i3, %B + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} + +define i32 @test9_use3(i32 %A, i32 %B) { +; CHECK-LABEL: @test9_use3( +; CHECK-NEXT:[[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT:[[I2:%.*]] = xor i32 [[I]], -1 +; CHECK-NEXT:tail call void @use(i32 [[I2]]) +; CHECK-NEXT:[[I3:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT:[[I4:%.*]] = and i32 [[I3]], [[B]] +; CHECK-NEXT:tail call void @use(i32 [[I4]]) +; CHECK-NEXT:[[I5:%.*]] = or i32 [[I4]], [[I2]] +; CHECK-NEXT:ret i32 [[I5]] +; + %i = or i32 %B, %A + %i2 = xor i32 %i, -1 + tail call void @use(i32 %i2) + %i3 = xor i32 %A, -1 + %i4 = and i32 %i3, %B + tail call void @use(i32 %i4) + %i5 = or i32 %i4, %i2 + ret i32 %i5 +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] a150010 - [SimplifyCFG] Optimize CFG when null is passed to a function with nonnull argument
Author: Dávid Bolvanský Date: 2021-01-15T23:53:43+01:00 New Revision: a1500105ee6074f992f376c916dcfa3a54acb717 URL: https://github.com/llvm/llvm-project/commit/a1500105ee6074f992f376c916dcfa3a54acb717 DIFF: https://github.com/llvm/llvm-project/commit/a1500105ee6074f992f376c916dcfa3a54acb717.diff LOG: [SimplifyCFG] Optimize CFG when null is passed to a function with nonnull argument Example: ``` __attribute__((nonnull,noinline)) char * pinc(char *p) { return ++p; } char * foo(bool b, char *a) { return pinc(b ? 0 : a); } ``` optimize to ``` char * foo(bool b, char *a) { return pinc(a); } ``` Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D94180 Added: Modified: llvm/lib/Transforms/Utils/SimplifyCFG.cpp llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll Removed: diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 559830ed9a17..7fe33fd3c759 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1345,7 +1345,7 @@ static bool isSafeToHoistInvoke(BasicBlock *BB1, BasicBlock *BB2, return true; } -static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I); +static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified = false); /// Given a conditional branch that goes to BB1 and BB2, hoist any common code /// in the two blocks up into the branch block. The caller of this function @@ -6545,7 +6545,7 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> ) { } /// Check if passing a value to an instruction will cause undefined behavior. -static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I) { +static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified) { Constant *C = dyn_cast(V); if (!C) return false; @@ -6568,12 +6568,15 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I) { // Look through GEPs. A load from a GEP derived from NULL is still undefined if (GetElementPtrInst *GEP = dyn_cast(Use)) - if (GEP->getPointerOperand() == I) -return passingValueIsAlwaysUndefined(V, GEP); + if (GEP->getPointerOperand() == I) { +if (!GEP->isInBounds() || !GEP->hasAllZeroIndices()) + PtrValueMayBeModified = true; +return passingValueIsAlwaysUndefined(V, GEP, PtrValueMayBeModified); + } // Look through bitcasts. if (BitCastInst *BC = dyn_cast(Use)) - return passingValueIsAlwaysUndefined(V, BC); + return passingValueIsAlwaysUndefined(V, BC, PtrValueMayBeModified); // Load from null is undefined. if (LoadInst *LI = dyn_cast(Use)) @@ -6588,10 +6591,35 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I) { SI->getPointerAddressSpace())) && SI->getPointerOperand() == I; -// A call to null is undefined. -if (auto *CB = dyn_cast(Use)) - return !NullPointerIsDefined(CB->getFunction()) && - CB->getCalledOperand() == I; +if (auto *CB = dyn_cast(Use)) { + if (C->isNullValue() && NullPointerIsDefined(CB->getFunction())) +return false; + // A call to null is undefined. + if (CB->getCalledOperand() == I) +return true; + + if (C->isNullValue()) { +for (const llvm::Use : CB->args()) + if (Arg == I) { +unsigned ArgIdx = CB->getArgOperandNo(); +if (CB->paramHasAttr(ArgIdx, Attribute::NonNull) && +CB->paramHasAttr(ArgIdx, Attribute::NoUndef)) { + // Passing null to a nonnnull+noundef argument is undefined. + return !PtrValueMayBeModified; +} + } + } else if (isa(C)) { +// Passing undef to a noundef argument is undefined. +for (const llvm::Use : CB->args()) + if (Arg == I) { +unsigned ArgIdx = CB->getArgOperandNo(); +if (CB->paramHasAttr(ArgIdx, Attribute::NoUndef)) { + // Passing undef to a noundef argument is undefined. + return true; +} + } + } +} } return false; } diff --git a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll index b3b7abe9ff0d..4c984819cfcf 100644 --- a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll +++ b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll @@ -69,7 +69,6 @@ define void @test5(i1 %cond, i8* %ptr) { ; CHECK-NEXT:store i8 2, i8* [[PTR:%.*]], align 8 ; CHECK-NEXT:ret void ; - entry: br i1 %cond, label %bb1, label %bb3 @@ -88,11 +87,10 @@ bb2: define void @test5_no_null_opt(i1 %cond, i8* %ptr) #0 { ; CHECK-LABEL: @test5_no_null_opt( ;
[llvm-branch-commits] [llvm] d307d89 - [Tests] Added test for memcpy loop idiom recognization
Author: Dávid Bolvanský Date: 2021-01-13T14:55:46+01:00 New Revision: d307d892ade9384a5d8b40ddb6a9c0b2dffbdb81 URL: https://github.com/llvm/llvm-project/commit/d307d892ade9384a5d8b40ddb6a9c0b2dffbdb81 DIFF: https://github.com/llvm/llvm-project/commit/d307d892ade9384a5d8b40ddb6a9c0b2dffbdb81.diff LOG: [Tests] Added test for memcpy loop idiom recognization Added: llvm/test/Transforms/LoopIdiom/memcpy.ll Modified: Removed: diff --git a/llvm/test/Transforms/LoopIdiom/memcpy.ll b/llvm/test/Transforms/LoopIdiom/memcpy.ll new file mode 100644 index ..af8dc773c19b --- /dev/null +++ b/llvm/test/Transforms/LoopIdiom/memcpy.ll @@ -0,0 +1,106 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -basic-aa -loop-idiom < %s -S | FileCheck %s + +define void @copy_both_noalias(float* noalias nocapture %d, float* noalias nocapture readonly %s, i64 %sz) { +; CHECK-LABEL: @copy_both_noalias( +; CHECK-NEXT: entry: +; CHECK-NEXT:[[D1:%.*]] = bitcast float* [[D:%.*]] to i8* +; CHECK-NEXT:[[S2:%.*]] = bitcast float* [[S:%.*]] to i8* +; CHECK-NEXT:[[EXITCOND_NOT1:%.*]] = icmp eq i64 [[SZ:%.*]], 0 +; CHECK-NEXT:br i1 [[EXITCOND_NOT1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT:[[TMP0:%.*]] = shl nuw i64 [[SZ]], 2 +; CHECK-NEXT:call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[D1]], i8* align 4 [[S2]], i64 [[TMP0]], i1 false) +; CHECK-NEXT:br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT:[[I_04:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT:[[D_ADDR_03:%.*]] = phi float* [ [[INCDEC_PTR1:%.*]], [[FOR_BODY]] ], [ [[D]], [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT:[[S_ADDR_02:%.*]] = phi float* [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[S]], [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT:[[INCDEC_PTR]] = getelementptr inbounds float, float* [[S_ADDR_02]], i64 1 +; CHECK-NEXT:[[TMP1:%.*]] = load float, float* [[S_ADDR_02]], align 4 +; CHECK-NEXT:[[INCDEC_PTR1]] = getelementptr inbounds float, float* [[D_ADDR_03]], i64 1 +; CHECK-NEXT:[[INC]] = add i64 [[I_04]], 1 +; CHECK-NEXT:[[EXITCOND_NOT:%.*]] = icmp eq i64 [[INC]], [[SZ]] +; CHECK-NEXT:br i1 [[EXITCOND_NOT]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.end.loopexit: +; CHECK-NEXT:br label [[FOR_END]] +; CHECK: for.end: +; CHECK-NEXT:ret void +; +entry: + %exitcond.not1 = icmp eq i64 %sz, 0 + br i1 %exitcond.not1, label %for.end, label %for.body.preheader + +for.body.preheader: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.preheader, %for.body + %i.04 = phi i64 [ %inc, %for.body ], [ 0, %for.body.preheader ] + %d.addr.03 = phi float* [ %incdec.ptr1, %for.body ], [ %d, %for.body.preheader ] + %s.addr.02 = phi float* [ %incdec.ptr, %for.body ], [ %s, %for.body.preheader ] + %incdec.ptr = getelementptr inbounds float, float* %s.addr.02, i64 1 + %0 = load float, float* %s.addr.02, align 4 + %incdec.ptr1 = getelementptr inbounds float, float* %d.addr.03, i64 1 + store float %0, float* %d.addr.03, align 4 + %inc = add i64 %i.04, 1 + %exitcond.not = icmp eq i64 %inc, %sz + br i1 %exitcond.not, label %for.end.loopexit, label %for.body + +for.end.loopexit: ; preds = %for.body + br label %for.end + +for.end: ; preds = %for.end.loopexit, %entry + ret void +} + +define void @copy_one_noalias(float* nocapture %d, float* noalias nocapture readonly %s, i64 %sz) { +; CHECK-LABEL: @copy_one_noalias( +; CHECK-NEXT: entry: +; CHECK-NEXT:[[D1:%.*]] = bitcast float* [[D:%.*]] to i8* +; CHECK-NEXT:[[S2:%.*]] = bitcast float* [[S:%.*]] to i8* +; CHECK-NEXT:[[EXITCOND_NOT1:%.*]] = icmp eq i64 [[SZ:%.*]], 0 +; CHECK-NEXT:br i1 [[EXITCOND_NOT1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT:[[TMP0:%.*]] = shl nuw i64 [[SZ]], 2 +; CHECK-NEXT:call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[D1]], i8* align 4 [[S2]], i64 [[TMP0]], i1 false) +; CHECK-NEXT:br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT:[[I_04:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT:[[D_ADDR_03:%.*]] = phi float* [ [[INCDEC_PTR1:%.*]], [[FOR_BODY]] ], [ [[D]], [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT:[[S_ADDR_02:%.*]] = phi float* [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[S]], [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT:[[INCDEC_PTR]] = getelementptr inbounds float, float* [[S_ADDR_02]], i64 1 +; CHECK-NEXT:[[TMP1:%.*]] = load float, float* [[S_ADDR_02]], align 4 +; CHECK-NEXT:[[INCDEC_PTR1]] =
[llvm-branch-commits] [llvm] 0529946 - [instCombine] Add (A ^ B) | ~(A | B) -> ~(A & B)
Author: Dávid Bolvanský Date: 2021-01-12T19:29:17+01:00 New Revision: 0529946b5bafafd10d77b946ee9fa96f388860ef URL: https://github.com/llvm/llvm-project/commit/0529946b5bafafd10d77b946ee9fa96f388860ef DIFF: https://github.com/llvm/llvm-project/commit/0529946b5bafafd10d77b946ee9fa96f388860ef.diff LOG: [instCombine] Add (A ^ B) | ~(A | B) -> ~(A & B) define i32 @src(i32 %x, i32 %y) { %0: %xor = xor i32 %y, %x %or = or i32 %y, %x %neg = xor i32 %or, 4294967295 %or1 = or i32 %xor, %neg ret i32 %or1 } => define i32 @tgt(i32 %x, i32 %y) { %0: %and = and i32 %x, %y %neg = xor i32 %and, 4294967295 ret i32 %neg } Transformation seems to be correct! https://alive2.llvm.org/ce/z/Cvca4a Added: Modified: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp llvm/test/Transforms/InstCombine/or.ll Removed: diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 15dcf2d19c15..352126fa07ca 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1627,6 +1627,14 @@ static Instruction *foldOrToXor(BinaryOperator , match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B) return BinaryOperator::CreateNot(Builder.CreateXor(A, B)); + // Operand complexity canonicalization guarantees that the 'xor' is Op0. + // (A ^ B) | ~(A | B) --> ~(A & B) + // (A ^ B) | ~(B | A) --> ~(A & B) + if (Op0->hasOneUse() || Op1->hasOneUse()) +if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && +match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B) + return BinaryOperator::CreateNot(Builder.CreateAnd(A, B)); + // (A & ~B) | (~A & B) --> A ^ B // (A & ~B) | (B & ~A) --> A ^ B // (~B & A) | (~A & B) --> A ^ B diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll index d41b8d53dd40..b5da1734c102 100644 --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -1004,10 +1004,8 @@ end: define i32 @test1(i32 %x, i32 %y) { ; CHECK-LABEL: @test1( -; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y]], [[X]] -; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 -; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:[[TMP1:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT:ret i32 [[OR1]] ; %xor = xor i32 %y, %x @@ -1019,13 +1017,11 @@ define i32 @test1(i32 %x, i32 %y) { define i32 @test2(i32 %x, i32 %y) { ; CHECK-LABEL: @test2( -; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 -; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] -; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:[[TMP1:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT:ret i32 [[OR1]] ; - %or = or i32 %y, %x + %or = or i32 %x, %y %neg = xor i32 %or, -1 %xor = xor i32 %y, %x %or1 = or i32 %xor, %neg @@ -1034,25 +1030,21 @@ define i32 @test2(i32 %x, i32 %y) { define i32 @test3(i32 %x, i32 %y) { ; CHECK-LABEL: @test3( -; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 -; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] -; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:[[TMP1:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:[[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT:ret i32 [[OR1]] ; %or = or i32 %y, %x %neg = xor i32 %or, -1 - %xor = xor i32 %y, %x + %xor = xor i32 %x, %y %or1 = or i32 %xor, %neg ret i32 %or1 } define <2 x i32> @test4_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @test4_vec( -; CHECK-NEXT:[[OR:%.*]] = or <2 x i32> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT:[[NEG:%.*]] = xor <2 x i32> [[OR]], -; CHECK-NEXT:[[XOR:%.*]] = xor <2 x i32> [[Y]], [[X]] -; CHECK-NEXT:[[OR1:%.*]] = or <2 x i32> [[XOR]], [[NEG]] +; CHECK-NEXT:[[TMP1:%.*]] = and <2 x i32> [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[OR1:%.*]] = xor <2 x i32> [[TMP1]], ; CHECK-NEXT:ret <2 x i32> [[OR1]] ; %or = or <2 x i32> %y, %x @@ -1066,9 +1058,9 @@ define i32 @test5_use(i32 %x, i32 %y) { ; CHECK-LABEL: @test5_use( ; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 -; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] ; CHECK-NEXT:call void @use(i32 [[NEG]]) -; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:[[TMP1:%.*]] = and i32 [[Y]], [[X]] +; CHECK-NEXT:[[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT:ret i32 [[OR1]] ; %or = or i32 %y, %x @@ -1081,11 +1073,10 @@ define i32 @test5_use(i32
[llvm-branch-commits] [llvm] bb9ebf6 - [Tests] Add tests for new InstCombine OR transformation, NFC
Author: Dávid Bolvanský Date: 2021-01-12T19:29:17+01:00 New Revision: bb9ebf6baf7057d7f2aed90fccbac2414cf9a134 URL: https://github.com/llvm/llvm-project/commit/bb9ebf6baf7057d7f2aed90fccbac2414cf9a134 DIFF: https://github.com/llvm/llvm-project/commit/bb9ebf6baf7057d7f2aed90fccbac2414cf9a134.diff LOG: [Tests] Add tests for new InstCombine OR transformation, NFC Added: Modified: llvm/test/Transforms/InstCombine/or.ll Removed: diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll index b5e3af2c7652..d41b8d53dd40 100644 --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -2,6 +2,7 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n32:64" +declare void @use(i32) define i32 @test12(i32 %A) { ; Should be eliminated @@ -1000,3 +1001,116 @@ end: %conv8 = zext i1 %t5 to i32 ret i32 %conv8 } + +define i32 @test1(i32 %x, i32 %y) { +; CHECK-LABEL: @test1( +; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y]], [[X]] +; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 +; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:ret i32 [[OR1]] +; + %xor = xor i32 %y, %x + %or = or i32 %y, %x + %neg = xor i32 %or, -1 + %or1 = or i32 %xor, %neg + ret i32 %or1 +} + +define i32 @test2(i32 %x, i32 %y) { +; CHECK-LABEL: @test2( +; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 +; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:ret i32 [[OR1]] +; + %or = or i32 %y, %x + %neg = xor i32 %or, -1 + %xor = xor i32 %y, %x + %or1 = or i32 %xor, %neg + ret i32 %or1 +} + +define i32 @test3(i32 %x, i32 %y) { +; CHECK-LABEL: @test3( +; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 +; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:ret i32 [[OR1]] +; + %or = or i32 %y, %x + %neg = xor i32 %or, -1 + %xor = xor i32 %y, %x + %or1 = or i32 %xor, %neg + ret i32 %or1 +} + +define <2 x i32> @test4_vec(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @test4_vec( +; CHECK-NEXT:[[OR:%.*]] = or <2 x i32> [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[NEG:%.*]] = xor <2 x i32> [[OR]], +; CHECK-NEXT:[[XOR:%.*]] = xor <2 x i32> [[Y]], [[X]] +; CHECK-NEXT:[[OR1:%.*]] = or <2 x i32> [[XOR]], [[NEG]] +; CHECK-NEXT:ret <2 x i32> [[OR1]] +; + %or = or <2 x i32> %y, %x + %neg = xor <2 x i32> %or, + %xor = xor <2 x i32> %y, %x + %or1 = or <2 x i32> %xor, %neg + ret <2 x i32> %or1 +} + +define i32 @test5_use(i32 %x, i32 %y) { +; CHECK-LABEL: @test5_use( +; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 +; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT:call void @use(i32 [[NEG]]) +; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:ret i32 [[OR1]] +; + %or = or i32 %y, %x + %neg = xor i32 %or, -1 + %xor = xor i32 %y, %x + call void @use(i32 %neg) + %or1 = or i32 %xor, %neg + ret i32 %or1 +} + +define i32 @test5_use2(i32 %x, i32 %y) { +; CHECK-LABEL: @test5_use2( +; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 +; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT:call void @use(i32 [[XOR]]) +; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:ret i32 [[OR1]] +; + %or = or i32 %y, %x + %neg = xor i32 %or, -1 + %xor = xor i32 %y, %x + call void @use(i32 %xor) + %or1 = or i32 %xor, %neg + ret i32 %or1 +} +define i32 @test5_use3(i32 %x, i32 %y) { +; CHECK-LABEL: @test5_use3( +; CHECK-NEXT:[[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[NEG:%.*]] = xor i32 [[OR]], -1 +; CHECK-NEXT:call void @use(i32 [[NEG]]) +; CHECK-NEXT:[[XOR:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT:call void @use(i32 [[XOR]]) +; CHECK-NEXT:[[OR1:%.*]] = or i32 [[XOR]], [[NEG]] +; CHECK-NEXT:ret i32 [[OR1]] +; + %or = or i32 %y, %x + %neg = xor i32 %or, -1 + call void @use(i32 %neg) + %xor = xor i32 %y, %x + call void @use(i32 %xor) + %or1 = or i32 %xor, %neg + ret i32 %or1 +} + ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] ae69fa9 - [InstCombine] Transform (A + B) - (A & B) to A | B (PR48604)
Author: Dávid Bolvanský Date: 2020-12-31T15:04:32+01:00 New Revision: ae69fa9b9f65f59cc0ca8c47f23748a53c8dbdc5 URL: https://github.com/llvm/llvm-project/commit/ae69fa9b9f65f59cc0ca8c47f23748a53c8dbdc5 DIFF: https://github.com/llvm/llvm-project/commit/ae69fa9b9f65f59cc0ca8c47f23748a53c8dbdc5.diff LOG: [InstCombine] Transform (A + B) - (A & B) to A | B (PR48604) define i32 @src(i32 %x, i32 %y) { %0: %a = add i32 %x, %y %o = and i32 %x, %y %r = sub i32 %a, %o ret i32 %r } => define i32 @tgt(i32 %x, i32 %y) { %0: %b = or i32 %x, %y ret i32 %b } Transformation seems to be correct! https://alive2.llvm.org/ce/z/2fhW6r Added: Modified: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp llvm/test/Transforms/InstCombine/sub.ll Removed: diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index be145615a241..bacb8689892a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1881,6 +1881,14 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator ) { return BinaryOperator::CreateAnd(A, B); } + // (sub (add A, B) (and A, B)) --> (or A, B) + { +Value *A, *B; +if (match(Op0, m_Add(m_Value(A), m_Value(B))) && +match(Op1, m_c_And(m_Specific(A), m_Specific(B + return BinaryOperator::CreateOr(A, B); + } + // (sub (and A, B) (or A, B)) --> neg (xor A, B) { Value *A, *B; diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll index aaac3f23f71f..649d2e8c2848 100644 --- a/llvm/test/Transforms/InstCombine/sub.ll +++ b/llvm/test/Transforms/InstCombine/sub.ll @@ -1621,9 +1621,7 @@ define <2 x i8> @and_vec(<2 x i8> %X, <2 x i8> %Y) { define i32 @or_test(i32 %x, i32 %y) { ; CHECK-LABEL: @or_test( -; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:[[B:%.*]] = and i32 [[X]], [[Y]] -; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[B]] +; CHECK-NEXT:[[R:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT:ret i32 [[R]] ; %a = add i32 %x, %y @@ -1634,9 +1632,7 @@ define i32 @or_test(i32 %x, i32 %y) { define i32 @or_test2(i32 %x, i32 %y) { ; CHECK-LABEL: @or_test2( -; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:[[B:%.*]] = and i32 [[Y]], [[X]] -; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[B]] +; CHECK-NEXT:[[R:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT:ret i32 [[R]] ; %a = add i32 %x, %y @@ -1647,9 +1643,7 @@ define i32 @or_test2(i32 %x, i32 %y) { define i32 @or_test3(i32 %x, i32 %y) { ; CHECK-LABEL: @or_test3( -; CHECK-NEXT:[[A:%.*]] = add i32 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT:[[B:%.*]] = and i32 [[X]], [[Y]] -; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[B]] +; CHECK-NEXT:[[R:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT:ret i32 [[R]] ; %a = add i32 %y, %x @@ -1660,9 +1654,7 @@ define i32 @or_test3(i32 %x, i32 %y) { define <2 x i8> @or_vec(<2 x i8> %X, <2 x i8> %Y) { ; CHECK-LABEL: @or_vec( -; CHECK-NEXT:[[A:%.*]] = add <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:[[B:%.*]] = and <2 x i8> [[X]], [[Y]] -; CHECK-NEXT:[[R:%.*]] = sub <2 x i8> [[A]], [[B]] +; CHECK-NEXT:[[R:%.*]] = or <2 x i8> [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT:ret <2 x i8> [[R]] ; %a = add <2 x i8> %X, %Y ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] c1937c2 - [NFC] Added/adjusted tests for PR48604; second pattern
Author: Dávid Bolvanský Date: 2020-12-31T14:59:15+01:00 New Revision: c1937c2af2a03f0b5fda3bbf99e2971ffa04ff0c URL: https://github.com/llvm/llvm-project/commit/c1937c2af2a03f0b5fda3bbf99e2971ffa04ff0c DIFF: https://github.com/llvm/llvm-project/commit/c1937c2af2a03f0b5fda3bbf99e2971ffa04ff0c.diff LOG: [NFC] Added/adjusted tests for PR48604; second pattern Added: Modified: llvm/test/Transforms/InstCombine/and.ll llvm/test/Transforms/InstCombine/sub.ll Removed: diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll index a3d5932ff140..020dbc483d9d 100644 --- a/llvm/test/Transforms/InstCombine/and.ll +++ b/llvm/test/Transforms/InstCombine/and.ll @@ -1217,49 +1217,3 @@ define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) { %C = and <2 x i8> %B, ret <2 x i8> %C } - - -define i32 @and_test(i32 %x, i32 %y) { -; CHECK-LABEL: @and_test( -; CHECK-NEXT:[[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:ret i32 [[R]] -; - %a = add i32 %x, %y - %o = or i32 %x, %y - %r = sub i32 %a, %o - ret i32 %r -} - -define i32 @and_test2(i32 %x, i32 %y) { -; CHECK-LABEL: @and_test2( -; CHECK-NEXT:[[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:ret i32 [[R]] -; - %a = add i32 %x, %y - %o = or i32 %y, %x - %r = sub i32 %a, %o - ret i32 %r -} - -define i32 @and_test3(i32 %x, i32 %y) { -; CHECK-LABEL: @and_test3( -; CHECK-NEXT:[[R:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT:ret i32 [[R]] -; - %a = add i32 %y, %x - %o = or i32 %x, %y - %r = sub i32 %a, %o - ret i32 %r -} - - -define <2 x i8> @and_vec(<2 x i8> %X, <2 x i8> %Y) { -; CHECK-LABEL: @and_vec( -; CHECK-NEXT:[[R:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:ret <2 x i8> [[R]] -; - %a = add <2 x i8> %X, %Y - %o = or <2 x i8> %X, %Y - %r = sub <2 x i8> %a, %o - ret <2 x i8> %r -} diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll index 066085fc2535..aaac3f23f71f 100644 --- a/llvm/test/Transforms/InstCombine/sub.ll +++ b/llvm/test/Transforms/InstCombine/sub.ll @@ -1574,3 +1574,99 @@ define i16 @sub_mul_nuw(i16 %x, i16 %y) { %r = sub i16 %x8, %y8 ret i16 %r } +define i32 @and_test(i32 %x, i32 %y) { +; CHECK-LABEL: @and_test( +; CHECK-NEXT:[[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %x, %y + %o = or i32 %x, %y + %r = sub i32 %a, %o + ret i32 %r +} + +define i32 @and_test2(i32 %x, i32 %y) { +; CHECK-LABEL: @and_test2( +; CHECK-NEXT:[[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %x, %y + %o = or i32 %y, %x + %r = sub i32 %a, %o + ret i32 %r +} + +define i32 @and_test3(i32 %x, i32 %y) { +; CHECK-LABEL: @and_test3( +; CHECK-NEXT:[[R:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %y, %x + %o = or i32 %x, %y + %r = sub i32 %a, %o + ret i32 %r +} + + +define <2 x i8> @and_vec(<2 x i8> %X, <2 x i8> %Y) { +; CHECK-LABEL: @and_vec( +; CHECK-NEXT:[[R:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:ret <2 x i8> [[R]] +; + %a = add <2 x i8> %X, %Y + %o = or <2 x i8> %X, %Y + %r = sub <2 x i8> %a, %o + ret <2 x i8> %r +} + +define i32 @or_test(i32 %x, i32 %y) { +; CHECK-LABEL: @or_test( +; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:[[B:%.*]] = and i32 [[X]], [[Y]] +; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[B]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %x, %y + %b = and i32 %x, %y + %r = sub i32 %a, %b + ret i32 %r +} + +define i32 @or_test2(i32 %x, i32 %y) { +; CHECK-LABEL: @or_test2( +; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:[[B:%.*]] = and i32 [[Y]], [[X]] +; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[B]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %x, %y + %b = and i32 %y, %x + %r = sub i32 %a, %b + ret i32 %r +} + +define i32 @or_test3(i32 %x, i32 %y) { +; CHECK-LABEL: @or_test3( +; CHECK-NEXT:[[A:%.*]] = add i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[B:%.*]] = and i32 [[X]], [[Y]] +; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[B]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %y, %x + %b = and i32 %x, %y + %r = sub i32 %a, %b + ret i32 %r +} + +define <2 x i8> @or_vec(<2 x i8> %X, <2 x i8> %Y) { +; CHECK-LABEL: @or_vec( +; CHECK-NEXT:[[A:%.*]] = add <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:[[B:%.*]] = and <2 x i8> [[X]], [[Y]] +; CHECK-NEXT:[[R:%.*]] = sub <2 x i8> [[A]], [[B]] +; CHECK-NEXT:ret <2 x i8> [[R]] +; + %a = add <2 x i8> %X, %Y + %b = and <2 x i8> %X, %Y + %r = sub <2 x i8> %a, %b + ret <2 x i8> %r +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org
[llvm-branch-commits] [llvm] 742ea77 - [InstCombine] Transform (A + B) - (A | B) to A & B (PR48604)
Author: Dávid Bolvanský Date: 2020-12-31T14:03:20+01:00 New Revision: 742ea77ca4c0ea10d8ccd160c7d7f4257d214ed0 URL: https://github.com/llvm/llvm-project/commit/742ea77ca4c0ea10d8ccd160c7d7f4257d214ed0 DIFF: https://github.com/llvm/llvm-project/commit/742ea77ca4c0ea10d8ccd160c7d7f4257d214ed0.diff LOG: [InstCombine] Transform (A + B) - (A | B) to A & B (PR48604) define i32 @src(i32 %x, i32 %y) { %0: %a = add i32 %x, %y %o = or i32 %x, %y %r = sub i32 %a, %o ret i32 %r } => define i32 @tgt(i32 %x, i32 %y) { %0: %b = and i32 %x, %y ret i32 %b } Transformation seems to be correct! https://alive2.llvm.org/ce/z/aQRh2j Added: Modified: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp llvm/test/Transforms/InstCombine/and.ll Removed: diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index c20861f20f07..be145615a241 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1873,6 +1873,14 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator ) { return BinaryOperator::CreateXor(A, B); } + // (sub (add A, B) (or A, B)) --> (and A, B) + { +Value *A, *B; +if (match(Op0, m_Add(m_Value(A), m_Value(B))) && +match(Op1, m_c_Or(m_Specific(A), m_Specific(B + return BinaryOperator::CreateAnd(A, B); + } + // (sub (and A, B) (or A, B)) --> neg (xor A, B) { Value *A, *B; diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll index 4f054c05889a..a3d5932ff140 100644 --- a/llvm/test/Transforms/InstCombine/and.ll +++ b/llvm/test/Transforms/InstCombine/and.ll @@ -1221,9 +1221,7 @@ define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) { define i32 @and_test(i32 %x, i32 %y) { ; CHECK-LABEL: @and_test( -; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:[[O:%.*]] = or i32 [[X]], [[Y]] -; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[O]] +; CHECK-NEXT:[[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT:ret i32 [[R]] ; %a = add i32 %x, %y @@ -1234,9 +1232,7 @@ define i32 @and_test(i32 %x, i32 %y) { define i32 @and_test2(i32 %x, i32 %y) { ; CHECK-LABEL: @and_test2( -; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:[[O:%.*]] = or i32 [[Y]], [[X]] -; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[O]] +; CHECK-NEXT:[[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT:ret i32 [[R]] ; %a = add i32 %x, %y @@ -1247,9 +1243,7 @@ define i32 @and_test2(i32 %x, i32 %y) { define i32 @and_test3(i32 %x, i32 %y) { ; CHECK-LABEL: @and_test3( -; CHECK-NEXT:[[A:%.*]] = add i32 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT:[[O:%.*]] = or i32 [[X]], [[Y]] -; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[O]] +; CHECK-NEXT:[[R:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT:ret i32 [[R]] ; %a = add i32 %y, %x @@ -1261,9 +1255,7 @@ define i32 @and_test3(i32 %x, i32 %y) { define <2 x i8> @and_vec(<2 x i8> %X, <2 x i8> %Y) { ; CHECK-LABEL: @and_vec( -; CHECK-NEXT:[[A:%.*]] = add <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT:[[O:%.*]] = or <2 x i8> [[X]], [[Y]] -; CHECK-NEXT:[[R:%.*]] = sub <2 x i8> [[A]], [[O]] +; CHECK-NEXT:[[R:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT:ret <2 x i8> [[R]] ; %a = add <2 x i8> %X, %Y ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 9b64939 - [NFC] Added tests for PR48604
Author: Dávid Bolvanský Date: 2020-12-31T14:03:20+01:00 New Revision: 9b6493946307c321cacc5d1da53bbae5a1acda24 URL: https://github.com/llvm/llvm-project/commit/9b6493946307c321cacc5d1da53bbae5a1acda24 DIFF: https://github.com/llvm/llvm-project/commit/9b6493946307c321cacc5d1da53bbae5a1acda24.diff LOG: [NFC] Added tests for PR48604 Added: Modified: llvm/test/Transforms/InstCombine/and.ll Removed: diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll index 020dbc483d9d..4f054c05889a 100644 --- a/llvm/test/Transforms/InstCombine/and.ll +++ b/llvm/test/Transforms/InstCombine/and.ll @@ -1217,3 +1217,57 @@ define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) { %C = and <2 x i8> %B, ret <2 x i8> %C } + + +define i32 @and_test(i32 %x, i32 %y) { +; CHECK-LABEL: @and_test( +; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:[[O:%.*]] = or i32 [[X]], [[Y]] +; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[O]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %x, %y + %o = or i32 %x, %y + %r = sub i32 %a, %o + ret i32 %r +} + +define i32 @and_test2(i32 %x, i32 %y) { +; CHECK-LABEL: @and_test2( +; CHECK-NEXT:[[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:[[O:%.*]] = or i32 [[Y]], [[X]] +; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[O]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %x, %y + %o = or i32 %y, %x + %r = sub i32 %a, %o + ret i32 %r +} + +define i32 @and_test3(i32 %x, i32 %y) { +; CHECK-LABEL: @and_test3( +; CHECK-NEXT:[[A:%.*]] = add i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT:[[O:%.*]] = or i32 [[X]], [[Y]] +; CHECK-NEXT:[[R:%.*]] = sub i32 [[A]], [[O]] +; CHECK-NEXT:ret i32 [[R]] +; + %a = add i32 %y, %x + %o = or i32 %x, %y + %r = sub i32 %a, %o + ret i32 %r +} + + +define <2 x i8> @and_vec(<2 x i8> %X, <2 x i8> %Y) { +; CHECK-LABEL: @and_vec( +; CHECK-NEXT:[[A:%.*]] = add <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT:[[O:%.*]] = or <2 x i8> [[X]], [[Y]] +; CHECK-NEXT:[[R:%.*]] = sub <2 x i8> [[A]], [[O]] +; CHECK-NEXT:ret <2 x i8> [[R]] +; + %a = add <2 x i8> %X, %Y + %o = or <2 x i8> %X, %Y + %r = sub <2 x i8> %a, %o + ret <2 x i8> %r +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 5da71a4 - [NFC] Added test for PR33549
Author: Dávid Bolvanský Date: 2020-12-09T03:21:52+01:00 New Revision: 5da71a4274acb86d31b74b79490cab30ac96bbf3 URL: https://github.com/llvm/llvm-project/commit/5da71a4274acb86d31b74b79490cab30ac96bbf3 DIFF: https://github.com/llvm/llvm-project/commit/5da71a4274acb86d31b74b79490cab30ac96bbf3.diff LOG: [NFC] Added test for PR33549 Added: llvm/test/Transforms/GVN/pr33549.ll Modified: Removed: diff --git a/llvm/test/Transforms/GVN/pr33549.ll b/llvm/test/Transforms/GVN/pr33549.ll new file mode 100644 index ..7155ba4c1e3d --- /dev/null +++ b/llvm/test/Transforms/GVN/pr33549.ll @@ -0,0 +1,91 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -gvn -S < %s | FileCheck %s + +@Data = common local_unnamed_addr global [32 x i32] zeroinitializer, align 4 + +; Function Attrs: norecurse nounwind +define void @testshl() local_unnamed_addr #0 { +; CHECK-LABEL: @testshl( +; CHECK-NEXT: entry: +; CHECK-NEXT:br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT:[[K_031:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[INC9:%.*]], [[FOR_INC8:%.*]] ] +; CHECK-NEXT:[[SHL:%.*]] = shl i32 1, [[K_031]] +; CHECK-NEXT:[[SHR:%.*]] = ashr exact i32 [[SHL]], 1 +; CHECK-NEXT:[[CMP229:%.*]] = icmp slt i32 [[SHL]], 64 +; CHECK-NEXT:br i1 [[CMP229]], label [[FOR_BODY3_PREHEADER:%.*]], label [[FOR_INC8]] +; CHECK: for.body3.preheader: +; CHECK-NEXT:[[DIV:%.*]] = sdiv i32 [[SHR]], 2 +; CHECK-NEXT:br label [[FOR_BODY3:%.*]] +; CHECK: for.body3: +; CHECK-NEXT:[[I_030:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY3]] ], [ [[DIV]], [[FOR_BODY3_PREHEADER]] ] +; CHECK-NEXT:[[ADD:%.*]] = add nsw i32 [[I_030]], [[SHR]] +; CHECK-NEXT:[[ARRAYIDX:%.*]] = getelementptr inbounds [32 x i32], [32 x i32]* @Data, i32 0, i32 [[ADD]] +; CHECK-NEXT:[[ARRAYIDX4:%.*]] = getelementptr inbounds [32 x i32], [32 x i32]* @Data, i32 0, i32 [[I_030]] +; CHECK-NEXT:[[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4, [[TBAA3:!tbaa !.*]] +; CHECK-NEXT:[[TMP1:%.*]] = load i32, i32* [[ARRAYIDX4]], align 4, [[TBAA3]] +; CHECK-NEXT:[[SUB:%.*]] = sub nsw i32 [[TMP1]], [[TMP0]] +; CHECK-NEXT:store i32 [[SUB]], i32* [[ARRAYIDX]], align 4, [[TBAA3]] +; CHECK-NEXT:[[ADD7:%.*]] = add nsw i32 [[TMP1]], [[TMP0]] +; CHECK-NEXT:store i32 [[ADD7]], i32* [[ARRAYIDX4]], align 4, [[TBAA3]] +; CHECK-NEXT:[[INC]] = add nsw i32 [[I_030]], 1 +; CHECK-NEXT:[[CMP2:%.*]] = icmp slt i32 [[I_030]], 15 +; CHECK-NEXT:br i1 [[CMP2]], label [[FOR_BODY3]], label [[FOR_INC8]] +; CHECK: for.inc8: +; CHECK-NEXT:[[INC9]] = add nuw nsw i32 [[K_031]], 1 +; CHECK-NEXT:[[EXITCOND:%.*]] = icmp eq i32 [[INC9]], 8 +; CHECK-NEXT:br i1 [[EXITCOND]], label [[FOR_END10:%.*]], label [[FOR_BODY]] +; CHECK: for.end10: +; CHECK-NEXT:ret void +; +entry: + br label %for.body + +for.body: ; preds = %for.inc8, %entry + %k.031 = phi i32 [ 1, %entry ], [ %inc9, %for.inc8 ] + %shl = shl i32 1, %k.031 + %shr = ashr exact i32 %shl, 1 + %cmp229 = icmp slt i32 %shl, 64 + br i1 %cmp229, label %for.body3.preheader, label %for.inc8 + +for.body3.preheader: ; preds = %for.body + %div = sdiv i32 %shr, 2 + br label %for.body3 + +for.body3:; preds = %for.body3.preheader, %for.body3 + %i.030 = phi i32 [ %inc, %for.body3 ], [ %div, %for.body3.preheader ] + %add = add nsw i32 %i.030, %shr + %arrayidx = getelementptr inbounds [32 x i32], [32 x i32]* @Data, i32 0, i32 %add + %arrayidx4 = getelementptr inbounds [32 x i32], [32 x i32]* @Data, i32 0, i32 %i.030 + %0 = load i32, i32* %arrayidx, align 4, !tbaa !3 + %1 = load i32, i32* %arrayidx4, align 4, !tbaa !3 + %sub = sub nsw i32 %1, %0 + store i32 %sub, i32* %arrayidx, align 4, !tbaa !3 + %2 = load i32, i32* %arrayidx4, align 4, !tbaa !3 + %add7 = add nsw i32 %2, %0 + store i32 %add7, i32* %arrayidx4, align 4, !tbaa !3 + %inc = add nsw i32 %i.030, 1 + %cmp2 = icmp slt i32 %i.030, 15 + br i1 %cmp2, label %for.body3, label %for.inc8 + +for.inc8: ; preds = %for.body3, %for.body + %inc9 = add nuw nsw i32 %k.031, 1 + %exitcond = icmp eq i32 %inc9, 8 + br i1 %exitcond, label %for.end10, label %for.body + +for.end10:; preds = %for.inc8 + ret void +} + +attributes #0 = { norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-m7"