diff --git a/llvm/include/llvm/SandboxIR/Pass.h b/llvm/include/llvm/SandboxIR/Pass.h index 267389a8a87a2..54f7bb1cc4464 100644 --- a/llvm/include/llvm/SandboxIR/Pass.h +++ b/llvm/include/llvm/SandboxIR/Pass.h @@ -17,6 +17,7 @@ namespace llvm { class AAResults; class ScalarEvolution; class TargetTransformInfo; +class OptimizationRemarkEmitter; namespace sandboxir { @@ -27,17 +28,20 @@ class Analyses { AAResults *AA = nullptr; ScalarEvolution *SE = nullptr; TargetTransformInfo *TTI = nullptr; + OptimizationRemarkEmitter *ORE = nullptr; Analyses() = default; public: - Analyses(AAResults &AA, ScalarEvolution &SE, TargetTransformInfo &TTI) - : AA(&AA), SE(&SE), TTI(&TTI) {} + Analyses(AAResults &AA, ScalarEvolution &SE, TargetTransformInfo &TTI, + OptimizationRemarkEmitter &ORE) + : AA(&AA), SE(&SE), TTI(&TTI), ORE(&ORE) {} public: AAResults &getAA() const { return *AA; } ScalarEvolution &getScalarEvolution() const { return *SE; } TargetTransformInfo &getTTI() const { return *TTI; } + OptimizationRemarkEmitter &getORE() const { return *ORE; } /// For use by unit tests. static Analyses emptyForTesting() { return Analyses(); } }; diff --git a/llvm/include/llvm/SandboxIR/Utils.h b/llvm/include/llvm/SandboxIR/Utils.h index 5c6f0d9edd618..b37a56b5881d9 100644 --- a/llvm/include/llvm/SandboxIR/Utils.h +++ b/llvm/include/llvm/SandboxIR/Utils.h @@ -17,6 +17,7 @@ #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Verifier.h" #include "llvm/SandboxIR/Function.h" #include "llvm/SandboxIR/Instruction.h" @@ -131,6 +132,15 @@ class Utils { const auto &LLVMF = *cast(F->Val); return llvm::verifyFunction(LLVMF, &OS); } + + /// Returns an optimization remark for \p I's location. + // TODO: OptimizationRemark can leak llvm IR through getRegion(). + static OptimizationRemark getOptimizationRemark(const char *PassName, + StringRef RemarkName, + Instruction *I) { + return OptimizationRemark(PassName, RemarkName, + cast(I->Val)); + } }; } // namespace llvm::sandboxir diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Debug.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Debug.h index 85b25c0249e7d..bf0b55f635b9b 100644 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Debug.h +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Debug.h @@ -15,7 +15,8 @@ #include "llvm/Support/Debug.h" -#define DEBUG_TYPE "sandbox-vectorizer" +#define PASS_NAME "sandbox-vectorizer" +#define DEBUG_TYPE PASS_NAME #define DEBUG_PREFIX "SBVec: " #endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_DEBUG_H diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h index fea53329719b9..6edbef180874c 100644 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h @@ -11,6 +11,7 @@ #include #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/IR/PassManager.h" #include "llvm/SandboxIR/Context.h" @@ -24,6 +25,7 @@ class SandboxVectorizerPass : public PassInfoMixin { TargetTransformInfo *TTI = nullptr; AAResults *AA = nullptr; ScalarEvolution *SE = nullptr; + OptimizationRemarkEmitter *ORE = nullptr; // NOTE: We define the Context as a pass-scope object instead of local object // in runOnFunction() because the passes defined in the pass-manager need // access to it for registering/deregistering callbacks during construction diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp index ec929fb3c71e4..9a668c4782d83 100644 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/SandboxIR/Utils.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InstructionCost.h" #include "llvm/Transforms/Vectorize/SandboxVectorizer/Debug.h" @@ -29,9 +31,13 @@ bool TransactionAcceptOrRevert::runOnRegion(Region &Rgn, const Analyses &A) { << CostAfter << "/" << CostThreshold << ")\n"); // TODO: Print costs / write to remarks. auto &Tracker = Rgn.getContext().getTracker(); - if (CostAfterMinusBefore < -CostThreshold) { + if (!Rgn.empty() && CostAfterMinusBefore < -CostThreshold) { bool HasChanges = !Tracker.empty(); Tracker.accept(); + // TODO: Use a more accurate debug location than Rgn.begin(). + A.getORE().emit( + Utils::getOptimizationRemark(PASS_NAME, "Vectorized", *Rgn.begin()) + << "Vectorized with cost " << ore::NV("Cost", CostAfterMinusBefore)); LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "*** Transaction Accept ***\n"); return HasChanges; } diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp index 20186426a5259..f0e70548ebc2b 100644 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp @@ -72,6 +72,7 @@ PreservedAnalyses SandboxVectorizerPass::run(Function &F, TTI = &AM.getResult(F); AA = &AM.getResult(F); SE = &AM.getResult(F); + ORE = &AM.getResult(F); bool Changed = runImpl(F); if (!Changed) @@ -132,7 +133,7 @@ bool SandboxVectorizerPass::runImpl(Function &LLVMF) { // Create SandboxIR for LLVMF and run BottomUpVec on it. sandboxir::Function &F = *Ctx->createFunction(&LLVMF); - sandboxir::Analyses A(*AA, *SE, *TTI); + sandboxir::Analyses A(*AA, *SE, *TTI, *ORE); bool Change = FPM.runOnFunction(F, A); // Given that sandboxir::Context `Ctx` is defined at a pass-level scope, the // maps from LLVM IR to Sandbox IR may go stale as later passes remove LLVM IR diff --git a/llvm/test/Transforms/SandboxVectorizer/remarks.ll b/llvm/test/Transforms/SandboxVectorizer/remarks.ll new file mode 100644 index 0000000000000..56b3fa8716790 --- /dev/null +++ b/llvm/test/Transforms/SandboxVectorizer/remarks.ll @@ -0,0 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: FileCheck --input-file=%t --check-prefix=REMARKS %s + +; REMARKS-LABEL: --- !Passed +; REMARKS-LABEL: Pass: sandbox-vectorizer +; REMARKS-LABEL: Name: Vectorized +; REMARKS-LABEL: Function: remarks1 +; REMARKS-LABEL: Args: +; REMARKS-LABEL: - String: 'Vectorized with cost ' +; REMARKS-LABEL: - Cost: '-3' + +define void @remarks1(ptr %ptr) { +; CHECK-LABEL: define void @remarks1( +; CHECK-SAME: ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0 +; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4, !sandboxvec [[META0:![0-9]+]] +; CHECK-NEXT: store <2 x float> [[VECL]], ptr [[PTR0]], align 4, !sandboxvec [[META0]] +; CHECK-NEXT: ret void +; + %ptr0 = getelementptr float, ptr %ptr, i32 0 + %ptr1 = getelementptr float, ptr %ptr, i32 1 + %ld0 = load float, ptr %ptr0 + %ld1 = load float, ptr %ptr1 + store float %ld0, ptr %ptr0 + store float %ld1, ptr %ptr1 + ret void +} +;. +; CHECK: [[META0]] = distinct !{!"sandboxregion"} +;. diff --git a/llvm/test/Transforms/SandboxVectorizer/remarks_not_vectorized.ll b/llvm/test/Transforms/SandboxVectorizer/remarks_not_vectorized.ll new file mode 100644 index 0000000000000..e0638b9418297 --- /dev/null +++ b/llvm/test/Transforms/SandboxVectorizer/remarks_not_vectorized.ll @@ -0,0 +1,50 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -passes=sandbox-vectorizer -sbvec-cost-threshold=-9999 -sbvec-vec-reg-bits=1024 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: FileCheck --allow-empty --input-file=%t --check-prefix=REMARKS %s + +; REMARKS-NOT: .* + +; Check that we don't get any remarks when the code isn't vectorized +; but the threshold allows it. +define void @no_remarks1(ptr %ptr) { +; CHECK-LABEL: define void @no_remarks1( +; CHECK-SAME: ptr [[PTR:%.*]]) { +; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0 +; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 42 +; CHECK-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4 +; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4 +; CHECK-NEXT: store float [[LD0]], ptr [[PTR0]], align 4 +; CHECK-NEXT: store float [[LD1]], ptr [[PTR1]], align 4 +; CHECK-NEXT: ret void +; + %ptr0 = getelementptr float, ptr %ptr, i32 0 + %ptr1 = getelementptr float, ptr %ptr, i32 42 + %ld0 = load float, ptr %ptr0 + %ld1 = load float, ptr %ptr1 + store float %ld0, ptr %ptr0 + store float %ld1, ptr %ptr1 + ret void +} + +; Same but doesn't get vectorized because of scheduling. +define void @no_remarks2(ptr %ptr, ptr %ptrX) { +; CHECK-LABEL: define void @no_remarks2( +; CHECK-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]]) { +; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0 +; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1 +; CHECK-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4 +; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4 +; CHECK-NEXT: store float [[LD0]], ptr [[PTR0]], align 4 +; CHECK-NEXT: store float 0.000000e+00, ptr [[PTRX]], align 4 +; CHECK-NEXT: store float [[LD1]], ptr [[PTR1]], align 4 +; CHECK-NEXT: ret void +; + %ptr0 = getelementptr float, ptr %ptr, i32 0 + %ptr1 = getelementptr float, ptr %ptr, i32 1 + %ld0 = load float, ptr %ptr0 + %ld1 = load float, ptr %ptr1 + store float %ld0, ptr %ptr0 + store float 0.0, ptr %ptrX + store float %ld1, ptr %ptr1 + ret void +} diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerTest.cpp index e9b304618a06c..f5b7920e41729 100644 --- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerTest.cpp @@ -57,6 +57,7 @@ define void @foo() { AM.registerPass([] { return AssumptionAnalysis(); }); AM.registerPass([] { return DominatorTreeAnalysis(); }); AM.registerPass([] { return LoopAnalysis(); }); + AM.registerPass([] { return OptimizationRemarkEmitterAnalysis(); }); SVecPass.run(LLVMF, AM); // This shouldn't crash. SVecPass.run(LLVMF, AM);