Index: bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli =================================================================== --- bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli +++ bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli @@ -186,6 +186,11 @@ : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit = "llvm_add_lower_expect_intrinsic" +(** See the [llvm::createLowerIsConstantIntrinsicPass] function. *) +external add_lower_is_constant_intrinsic + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_is_constant_intrinsic" + (** See the [llvm::createTypeBasedAliasAnalysisPass] function. *) external add_type_based_alias_analysis : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit Index: bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c =================================================================== --- bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c +++ bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c @@ -232,6 +232,12 @@ } /* [ unit */ +CAMLprim value llvm_add_lower_is_constant_intrinsic(LLVMPassManagerRef PM) { + LLVMAddLowerIsConstantIntrinsicPass(PM); + return Val_unit; +} + +/* [ unit */ CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) { LLVMAddTypeBasedAliasAnalysisPass(PM); return Val_unit; Index: include/llvm-c/Transforms/Scalar.h =================================================================== --- include/llvm-c/Transforms/Scalar.h +++ include/llvm-c/Transforms/Scalar.h @@ -144,6 +144,9 @@ /** See llvm::createLowerExpectIntrinsicPass function */ void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM); +/** See llvm::createLowerIsConstantIntrinsicPass function */ +void LLVMAddLowerIsConstantIntrinsicPass(LLVMPassManagerRef PM); + /** See llvm::createTypeBasedAliasAnalysisPass function */ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); Index: include/llvm/Analysis/InstructionSimplify.h =================================================================== --- include/llvm/Analysis/InstructionSimplify.h +++ include/llvm/Analysis/InstructionSimplify.h @@ -254,7 +254,8 @@ /// See if we can compute a simplified version of this instruction. If not, /// return null. Value *SimplifyInstruction(Instruction *I, const SimplifyQuery &Q, - OptimizationRemarkEmitter *ORE = nullptr); + OptimizationRemarkEmitter *ORE = nullptr, + bool SimplifyCFG = false); /// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively. /// @@ -261,12 +262,14 @@ /// This first performs a normal RAUW of I with SimpleV. It then recursively /// attempts to simplify those users updated by the operation. The 'I' /// instruction must not be equal to the simplified value 'SimpleV'. +/// If SimplifyCFG is set, it will also adjust no-longer conditional branches. /// /// The function returns true if any simplifications were performed. bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionCache *AC = nullptr); + AssumptionCache *AC = nullptr, + bool SimplifyCFG = false); /// Recursively attempt to simplify an instruction. /// @@ -274,10 +277,12 @@ /// replaces uses of 'I' with the simplified value. It then recurses on each /// of the users impacted. It returns true if any simplifications were /// performed. +/// If SimplifyCFG is set, it will also adjust no-longer conditional branches. bool recursivelySimplifyInstruction(Instruction *I, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionCache *AC = nullptr); + AssumptionCache *AC = nullptr, + bool SimplifyCFG = false); // These helper functions return a SimplifyQuery structure that contains as // many of the optional analysis we use as are currently valid. This is the Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -244,6 +244,7 @@ void initializeLowerEmuTLSPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&); +void initializeLowerIsConstantIntrinsicPass(PassRegistry&); void initializeLowerWidenableConditionLegacyPassPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokeLegacyPassPass(PassRegistry&); Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -141,6 +141,7 @@ (void) llvm::createLoopIdiomPass(); (void) llvm::createLoopRotatePass(); (void) llvm::createLowerExpectIntrinsicPass(); + (void) llvm::createLowerIsConstantIntrinsicPass(); (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSwitchPass(); (void) llvm::createNaryReassociatePass(); Index: include/llvm/Transforms/Scalar.h =================================================================== --- include/llvm/Transforms/Scalar.h +++ include/llvm/Transforms/Scalar.h @@ -397,6 +397,13 @@ //===----------------------------------------------------------------------===// // +// LowerIsConstantIntrinsics - Converts llvm.is.constant intrinsics into 'true' +// or 'false'. +// +FunctionPass *createLowerIsConstantIntrinsicPass(); + +//===----------------------------------------------------------------------===// +// // PartiallyInlineLibCalls - Tries to inline the fast path of library // calls such as sqrt. // Index: include/llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h =================================================================== --- include/llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h +++ include/llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h @@ -0,0 +1,40 @@ +//===- LowerIsConstantIntrinsic.h - Lower is.constant int. pass -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// The header file for the LowerIsConstantIntrinsic pass as used by the new pass +/// manager. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_LOWERISCONSTANTINTRINSIC_H +#define LLVM_TRANSFORMS_SCALAR_LOWERISCONSTANTINTRINSIC_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct LowerIsConstantIntrinsicPass : + PassInfoMixin { +public: + explicit LowerIsConstantIntrinsicPass() {} + + /// Run the pass over the function. + /// + /// This will lower all remaining 'is.constant'` intrinsic calls in this + /// function into 'true' or 'false', propagate the constants and just + /// conditional branches. + /// The pass complements the normal Instruction Simplification for folding + /// 'is.constant' to true in the optimized pass chain. + PreservedAnalyses run(Function &F, FunctionAnalysisManager &); +}; + +} + +#endif Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -5044,11 +5044,26 @@ return ConstantFoldCall(Call, F, ConstantArgs, Q.TLI); } +static Value *simplifyBranch(BranchInst *BI, bool SimplifyCFG) { + if (!SimplifyCFG || BI->isUnconditional()) + return nullptr; + if (match(BI->getOperand(0), m_Zero())) { + BI->setSuccessor(0, BI->getSuccessor(1)); + return nullptr; + } + if (match(BI->getOperand(0), m_One())) { + BI->setSuccessor(1, BI->getSuccessor(0)); + return nullptr; + } + return nullptr; +} + /// See if we can compute a simplified version of this instruction. /// If not, this returns null. Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ, - OptimizationRemarkEmitter *ORE) { + OptimizationRemarkEmitter *ORE, + bool SimplifyCFG) { const SimplifyQuery Q = SQ.CxtI ? SQ : SQ.getWithInstruction(I); Value *Result; @@ -5056,6 +5071,9 @@ default: Result = ConstantFoldInstruction(I, Q.DL, Q.TLI); break; + case Instruction::Br: + Result = simplifyBranch(dyn_cast(I), SimplifyCFG); + break; case Instruction::FNeg: Result = SimplifyFNegInst(I->getOperand(0), I->getFastMathFlags(), Q); break; @@ -5226,7 +5244,8 @@ static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI, const DominatorTree *DT, - AssumptionCache *AC) { + AssumptionCache *AC, + bool SimplifyCFG) { bool Simplified = false; SmallSetVector Worklist; const DataLayout &DL = I->getModule()->getDataLayout(); @@ -5255,7 +5274,7 @@ I = Worklist[Idx]; // See if this instruction simplifies. - SimpleV = SimplifyInstruction(I, {DL, TLI, DT, AC}); + SimpleV = SimplifyInstruction(I, {DL, TLI, DT, AC}, nullptr, SimplifyCFG); if (!SimpleV) continue; @@ -5282,17 +5301,21 @@ bool llvm::recursivelySimplifyInstruction(Instruction *I, const TargetLibraryInfo *TLI, const DominatorTree *DT, - AssumptionCache *AC) { - return replaceAndRecursivelySimplifyImpl(I, nullptr, TLI, DT, AC); + AssumptionCache *AC, + bool SimplifyCFG) { + return replaceAndRecursivelySimplifyImpl(I, nullptr, TLI, DT, AC, + SimplifyCFG); } bool llvm::replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI, const DominatorTree *DT, - AssumptionCache *AC) { + AssumptionCache *AC, + bool SimplifyCFG) { assert(I != SimpleV && "replaceAndRecursivelySimplify(X,X) is not valid!"); assert(SimpleV && "Must provide a simplified value."); - return replaceAndRecursivelySimplifyImpl(I, SimpleV, TLI, DT, AC); + return replaceAndRecursivelySimplifyImpl(I, SimpleV, TLI, DT, AC, + SimplifyCFG); } namespace llvm { Index: lib/CodeGen/TargetPassConfig.cpp =================================================================== --- lib/CodeGen/TargetPassConfig.cpp +++ lib/CodeGen/TargetPassConfig.cpp @@ -654,6 +654,7 @@ // TODO: add a pass insertion point here addPass(createGCLoweringPass()); addPass(createShadowStackGCLoweringPass()); + addPass(createLowerIsConstantIntrinsicPass()); // Make sure that no unreachable blocks are instruction selected. addPass(createUnreachableBlockEliminationPass()); Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -140,6 +140,7 @@ #include "llvm/Transforms/Scalar/LowerAtomic.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h" +#include "llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h" #include "llvm/Transforms/Scalar/LowerWidenableCondition.h" #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -185,6 +185,7 @@ FUNCTION_PASS("loweratomic", LowerAtomicPass()) FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass()) FUNCTION_PASS("lower-guard-intrinsic", LowerGuardIntrinsicPass()) +FUNCTION_PASS("lower-is-constant", LowerIsConstantIntrinsicPass()) FUNCTION_PASS("lower-widenable-condition", LowerWidenableConditionPass()) FUNCTION_PASS("guard-widening", GuardWideningPass()) FUNCTION_PASS("gvn", GVN()) Index: lib/Transforms/Scalar/CMakeLists.txt =================================================================== --- lib/Transforms/Scalar/CMakeLists.txt +++ lib/Transforms/Scalar/CMakeLists.txt @@ -46,6 +46,7 @@ LowerAtomic.cpp LowerExpectIntrinsic.cpp LowerGuardIntrinsic.cpp + LowerIsConstantIntrinsic.cpp LowerWidenableCondition.cpp MakeGuardsExplicit.cpp MemCpyOptimizer.cpp Index: lib/Transforms/Scalar/LowerIsConstantIntrinsic.cpp =================================================================== --- lib/Transforms/Scalar/LowerIsConstantIntrinsic.cpp +++ lib/Transforms/Scalar/LowerIsConstantIntrinsic.cpp @@ -0,0 +1,108 @@ +//===- LowerIsConstantIntrinsic.cpp - Lower is.constant intrinsic ---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This pass lowers the 'is.constant' intrinsic to 'true' or 'false'. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Pass.h" +#include "llvm/Support/Debug.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" + +using namespace llvm; + +#define DEBUG_TYPE "lower-is-constant-intrinsic" + +STATISTIC(IsConstantIntrinsicsHandled, + "Number of 'is.constant' intrinsic instructions handled"); + +static bool handleIsConstantIntrinsic(IntrinsicInst *II) { + Value *Op = II->getOperand(0); + Value *Exp = nullptr; + + if (isa(Op)) + Exp = ConstantInt::getTrue(II->getType()); + else + Exp = ConstantInt::getFalse(II->getType()); + + replaceAndRecursivelySimplify(II, Exp, nullptr, nullptr, nullptr, true); + return true; +} + +static bool lowerIsConstantIntrinsic(Function &F, + const TargetLibraryInfo *TLI) { + bool Changed = false; + +restart: + for (BasicBlock &BB : F) { + for (auto BI = BB.begin(), BE = BB.end(); BI != BE;) { + Instruction *I = &*BI++; + if (IntrinsicInst *II = dyn_cast(I)) { + if (II->getIntrinsicID() != Intrinsic::is_constant) + continue; + if (handleIsConstantIntrinsic(II)) { + IsConstantIntrinsicsHandled++; + Changed = true; + goto restart; + } + } + } + } + // XXX Depend on unreachable block removal + return Changed; +} + +PreservedAnalyses LowerIsConstantIntrinsicPass::run( + Function &F, FunctionAnalysisManager &AM) { + if (lowerIsConstantIntrinsic(F, AM.getCachedResult(F))) + return PreservedAnalyses::none(); + + return PreservedAnalyses::all(); +} + + +namespace { +/// Legacy pass for lowering is.constant intrinsics out of the IR. +/// +/// When this pass is run over a function it converts is.constant intrinsics +/// into 'true' or 'false'. This is completements the normal constand folding +/// to 'true' as part of Instruction Simplify passes. +class LowerIsConstantIntrinsic : public FunctionPass { +public: + static char ID; + LowerIsConstantIntrinsic() + : FunctionPass(ID) { + initializeLowerIsConstantIntrinsicPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + auto *TLIP = getAnalysisIfAvailable(); + const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI() : nullptr; + return lowerIsConstantIntrinsic(F, TLI); + } +}; +} + +char LowerIsConstantIntrinsic::ID = 0; +INITIALIZE_PASS(LowerIsConstantIntrinsic, "lower-is-constant", + "Lower 'is.constant' Intrinsics", false, false) + +FunctionPass *llvm::createLowerIsConstantIntrinsicPass() { + return new LowerIsConstantIntrinsic(); +} Index: lib/Transforms/Scalar/Scalar.cpp =================================================================== --- lib/Transforms/Scalar/Scalar.cpp +++ lib/Transforms/Scalar/Scalar.cpp @@ -81,6 +81,7 @@ initializeLowerAtomicLegacyPassPass(Registry); initializeLowerExpectIntrinsicPass(Registry); initializeLowerGuardIntrinsicLegacyPassPass(Registry); + initializeLowerIsConstantIntrinsicPass(Registry); initializeLowerWidenableConditionLegacyPassPass(Registry); initializeMemCpyOptLegacyPassPass(Registry); initializeMergeICmpsLegacyPassPass(Registry); @@ -284,6 +285,10 @@ unwrap(PM)->add(createLowerExpectIntrinsicPass()); } +void LLVMAddLowerIsConstantIntrinsicPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLowerIsConstantIntrinsicPass()); +} + void LLVMAddUnifyFunctionExitNodesPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createUnifyFunctionExitNodesPass()); } Index: utils/gn/secondary/llvm/lib/Transforms/Scalar/BUILD.gn =================================================================== --- utils/gn/secondary/llvm/lib/Transforms/Scalar/BUILD.gn +++ utils/gn/secondary/llvm/lib/Transforms/Scalar/BUILD.gn @@ -57,6 +57,7 @@ "LowerAtomic.cpp", "LowerExpectIntrinsic.cpp", "LowerGuardIntrinsic.cpp", + "LowerIsConstantIntrinsic.cpp", "LowerWidenableCondition.cpp", "MakeGuardsExplicit.cpp", "MemCpyOptimizer.cpp",