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 @@ -31,6 +31,7 @@ #ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H #define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H +#include "llvm/ADT/SetVector.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Operator.h" #include "llvm/IR/User.h" @@ -261,12 +262,16 @@ /// 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 Failed is provided, instructions that could not be simplified are +/// added to it. /// /// 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, + SmallSetVector + *Failed = nullptr); /// Recursively attempt to simplify an instruction. /// 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 @@ -5219,14 +5219,17 @@ /// If we have a pre-simplified value in 'SimpleV', that is forcibly used to /// replace the instruction 'I'. Otherwise, we simply add 'I' to the list of /// instructions to process and attempt to simplify it using -/// InstructionSimplify. +/// InstructionSimplify. Instructions that did not simplify are optionally added +/// to the Failed set for further processing by the caller. /// /// This routine returns 'true' only when *it* simplifies something. The passed /// in simplified value does not count toward this. static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI, const DominatorTree *DT, - AssumptionCache *AC) { + AssumptionCache *AC, + SmallSetVector + *Failed = nullptr) { bool Simplified = false; SmallSetVector Worklist; const DataLayout &DL = I->getModule()->getDataLayout(); @@ -5255,9 +5258,12 @@ I = Worklist[Idx]; // See if this instruction simplifies. - SimpleV = SimplifyInstruction(I, {DL, TLI, DT, AC}); - if (!SimpleV) + SimpleV = SimplifyInstruction(I, {DL, TLI, DT, AC}, nullptr); + if (!SimpleV) { + if (Failed) + Failed->insert(I); continue; + } Simplified = true; @@ -5283,16 +5289,18 @@ const TargetLibraryInfo *TLI, const DominatorTree *DT, AssumptionCache *AC) { - return replaceAndRecursivelySimplifyImpl(I, nullptr, TLI, DT, AC); + return replaceAndRecursivelySimplifyImpl(I, nullptr, TLI, DT, AC, nullptr); } bool llvm::replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI, const DominatorTree *DT, - AssumptionCache *AC) { + AssumptionCache *AC, + SmallSetVector + *Failed) { 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, Failed); } 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 @@ -141,6 +141,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 @@ -186,6 +186,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,127 @@ +//===- 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/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/IR/PatternMatch.h" +#include "llvm/Pass.h" +#include "llvm/Support/Debug.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h" +#include "llvm/Transforms/Utils/Local.h" + +using namespace llvm; +using namespace llvm::PatternMatch; + +#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()); + + SmallSetVector Worklist; + replaceAndRecursivelySimplify(II, Exp, nullptr, nullptr, nullptr, &Worklist); + for (auto I: Worklist) { + BranchInst *BI = dyn_cast(I); + if (!BI) + continue; + if (BI->isUnconditional()) + continue; + if (match(BI->getOperand(0), m_Zero())) { + BranchInst::Create(BI->getSuccessor(1), BI->getParent()); + BI->eraseFromParent(); + } else if (match(BI->getOperand(0), m_One())) { + BranchInst::Create(BI->getSuccessor(0), BI->getParent()); + BI->eraseFromParent(); + } + } + return true; +} + +static bool lowerIsConstantIntrinsic(Function &F, + const TargetLibraryInfo *TLI) { + bool NewChange, Changed = false; + + do { + NewChange = false; + for (BasicBlock &BB : F) { + for (BasicBlock::iterator DI = BB.begin(); DI != BB.end(); ) { + Instruction *Inst = &*DI++; + if (IntrinsicInst *II = dyn_cast(Inst)) { + if (II->getIntrinsicID() == Intrinsic::is_constant && + handleIsConstantIntrinsic(II)) { + IsConstantIntrinsicsHandled++; + Changed = true; + NewChange = true; + DI = BB.begin(); + continue; + } + } + } + } + } while (NewChange); + 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: test/CodeGen/AArch64/O0-pipeline.ll =================================================================== --- test/CodeGen/AArch64/O0-pipeline.ll +++ test/CodeGen/AArch64/O0-pipeline.ll @@ -21,6 +21,7 @@ ; CHECK-NEXT: Module Verifier ; CHECK-NEXT: Lower Garbage Collection Instructions ; CHECK-NEXT: Shadow Stack GC Lowering +; CHECK-NEXT: Lower 'is.constant' Intrinsics ; CHECK-NEXT: Remove unreachable blocks from the CFG ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining) ; CHECK-NEXT: Scalarize Masked Memory Intrinsics Index: test/CodeGen/AArch64/O3-pipeline.ll =================================================================== --- test/CodeGen/AArch64/O3-pipeline.ll +++ test/CodeGen/AArch64/O3-pipeline.ll @@ -38,6 +38,7 @@ ; CHECK-NEXT: Expand memcmp() to load/stores ; CHECK-NEXT: Lower Garbage Collection Instructions ; CHECK-NEXT: Shadow Stack GC Lowering +; CHECK-NEXT: Lower 'is.constant' Intrinsics ; CHECK-NEXT: Remove unreachable blocks from the CFG ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Natural Loop Information Index: test/CodeGen/ARM/O3-pipeline.ll =================================================================== --- test/CodeGen/ARM/O3-pipeline.ll +++ test/CodeGen/ARM/O3-pipeline.ll @@ -22,6 +22,7 @@ ; CHECK-NEXT: Expand memcmp() to load/stores ; CHECK-NEXT: Lower Garbage Collection Instructions ; CHECK-NEXT: Shadow Stack GC Lowering +; CHECK-NEXT: Lower 'is.constant' Intrinsics ; CHECK-NEXT: Remove unreachable blocks from the CFG ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Natural Loop Information Index: test/CodeGen/X86/O0-pipeline.ll =================================================================== --- test/CodeGen/X86/O0-pipeline.ll +++ test/CodeGen/X86/O0-pipeline.ll @@ -24,6 +24,7 @@ ; CHECK-NEXT: Module Verifier ; CHECK-NEXT: Lower Garbage Collection Instructions ; CHECK-NEXT: Shadow Stack GC Lowering +; CHECK-NEXT: Lower 'is.constant' Intrinsics ; CHECK-NEXT: Remove unreachable blocks from the CFG ; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining) ; CHECK-NEXT: Scalarize Masked Memory Intrinsics Index: test/CodeGen/X86/O3-pipeline.ll =================================================================== --- test/CodeGen/X86/O3-pipeline.ll +++ test/CodeGen/X86/O3-pipeline.ll @@ -35,6 +35,7 @@ ; CHECK-NEXT: Expand memcmp() to load/stores ; CHECK-NEXT: Lower Garbage Collection Instructions ; CHECK-NEXT: Shadow Stack GC Lowering +; CHECK-NEXT: Lower 'is.constant' Intrinsics ; CHECK-NEXT: Remove unreachable blocks from the CFG ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Natural Loop Information Index: test/CodeGen/X86/is-constant.ll =================================================================== --- test/CodeGen/X86/is-constant.ll +++ test/CodeGen/X86/is-constant.ll @@ -1,50 +0,0 @@ -; RUN: llc -O2 < %s | FileCheck %s --check-prefix=CHECK-O2 --check-prefix=CHECK -; RUN: llc -O0 -fast-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK -; RUN: llc -O0 -fast-isel=0 < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK -; RUN: llc -O0 -global-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK - -;; Ensure that an unfoldable is.constant gets lowered reasonably in -;; optimized codegen, in particular, that the "true" branch is -;; eliminated. -;; -;; This isn't asserting any specific output from non-optimized runs, -;; (e.g., currently the not-taken branch does not get eliminated). But -;; it does ensure that lowering succeeds in all 3 codegen paths. - -target triple = "x86_64-unknown-linux-gnu" - -declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone -declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone -declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone - -declare i32 @subfun_1() -declare i32 @subfun_2() - -define i32 @test_branch(i32 %in) nounwind { -; CHECK-LABEL: test_branch: -; CHECK-O2: %bb.0: -; CHECK-O2-NEXT: jmp subfun_2 - %v = call i1 @llvm.is.constant.i32(i32 %in) - br i1 %v, label %True, label %False - -True: - %call1 = tail call i32 @subfun_1() - ret i32 %call1 - -False: - %call2 = tail call i32 @subfun_2() - ret i32 %call2 -} - -;; llvm.objectsize is another tricky case which gets folded to -1 very -;; late in the game. We'd like to ensure that llvm.is.constant of -;; llvm.objectsize is true. -define i1 @test_objectsize(i8* %obj) nounwind { -; CHECK-LABEL: test_objectsize: -; CHECK-O2: %bb.0: -; CHECK-O2: movb $1, %al -; CHECK-O2-NEXT: retq - %os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false) - %v = call i1 @llvm.is.constant.i64(i64 %os) - ret i1 %v -} Index: test/Transforms/LowerIsConstant/is-constant.ll =================================================================== --- test/Transforms/LowerIsConstant/is-constant.ll +++ test/Transforms/LowerIsConstant/is-constant.ll @@ -1,29 +1,20 @@ -; RUN: llc -O2 < %s | FileCheck %s --check-prefix=CHECK-O2 --check-prefix=CHECK -; RUN: llc -O0 -fast-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK -; RUN: llc -O0 -fast-isel=0 < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK -; RUN: llc -O0 -global-isel < %s | FileCheck %s --check-prefix=CHECK-O0 --check-prefix=CHECK +; RUN: opt --lower-is-constant --unreachableblockelim -S < %s | FileCheck %s ;; Ensure that an unfoldable is.constant gets lowered reasonably in ;; optimized codegen, in particular, that the "true" branch is ;; eliminated. -;; -;; This isn't asserting any specific output from non-optimized runs, -;; (e.g., currently the not-taken branch does not get eliminated). But -;; it does ensure that lowering succeeds in all 3 codegen paths. -target triple = "x86_64-unknown-linux-gnu" +;; CHECK-NOT: tail call i32 @subfun_1() +;; CHECK: tail call i32 @subfun_2() +;; CHECK-NOT: tail call i32 @subfun_1() declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone -declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone declare i32 @subfun_1() declare i32 @subfun_2() define i32 @test_branch(i32 %in) nounwind { -; CHECK-LABEL: test_branch: -; CHECK-O2: %bb.0: -; CHECK-O2-NEXT: jmp subfun_2 %v = call i1 @llvm.is.constant.i32(i32 %in) br i1 %v, label %True, label %False @@ -35,16 +26,3 @@ %call2 = tail call i32 @subfun_2() ret i32 %call2 } - -;; llvm.objectsize is another tricky case which gets folded to -1 very -;; late in the game. We'd like to ensure that llvm.is.constant of -;; llvm.objectsize is true. -define i1 @test_objectsize(i8* %obj) nounwind { -; CHECK-LABEL: test_objectsize: -; CHECK-O2: %bb.0: -; CHECK-O2: movb $1, %al -; CHECK-O2-NEXT: retq - %os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false) - %v = call i1 @llvm.is.constant.i64(i64 %os) - ret i1 %v -} 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",