Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -239,6 +239,7 @@ void initializeLowerEmuTLSPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&); +void initializeLowerWidenableConditionLegacyPassPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokeLegacyPassPass(PassRegistry&); void initializeLowerSwitchPass(PassRegistry&); Index: include/llvm/Transforms/Scalar.h =================================================================== --- include/llvm/Transforms/Scalar.h +++ include/llvm/Transforms/Scalar.h @@ -360,6 +360,12 @@ //===----------------------------------------------------------------------===// // +// LowerWidenableCondition - Lower widenable condition to i1 true. +// +Pass *createLowerWidenableConditionPass(); + +//===----------------------------------------------------------------------===// +// // MergeICmps - Merge integer comparison chains into a memcmp // Pass *createMergeICmpsPass(); Index: include/llvm/Transforms/Scalar/LowerWidenableCondition.h =================================================================== --- /dev/null +++ include/llvm/Transforms/Scalar/LowerWidenableCondition.h @@ -0,0 +1,27 @@ +//===--- LowerWidenableCondition.h - Lower the guard intrinsic ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass lowers the llvm.widenable.condition intrinsic to default value +// which is i1 true. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TRANSFORMS_SCALAR_LOWERWIDENABLECONDITION_H +#define LLVM_TRANSFORMS_SCALAR_LOWERWIDENABLECONDITION_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct LowerWidenableConditionPass : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} + +#endif //LLVM_TRANSFORMS_SCALAR_LOWERWIDENABLECONDITION_H Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -131,6 +131,7 @@ #include "llvm/Transforms/Scalar/LowerAtomic.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h" +#include "llvm/Transforms/Scalar/LowerWidenableCondition.h" #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -177,6 +177,7 @@ FUNCTION_PASS("loweratomic", LowerAtomicPass()) FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass()) FUNCTION_PASS("lower-guard-intrinsic", LowerGuardIntrinsicPass()) +FUNCTION_PASS("lower-widenable-condition", LowerWidenableConditionPass()) FUNCTION_PASS("guard-widening", GuardWideningPass()) FUNCTION_PASS("gvn", GVN()) FUNCTION_PASS("load-store-vectorizer", LoadStoreVectorizerPass()) Index: lib/Transforms/Scalar/CMakeLists.txt =================================================================== --- lib/Transforms/Scalar/CMakeLists.txt +++ lib/Transforms/Scalar/CMakeLists.txt @@ -45,6 +45,7 @@ LowerAtomic.cpp LowerExpectIntrinsic.cpp LowerGuardIntrinsic.cpp + LowerWidenableCondition.cpp MakeGuardsExplicit.cpp MemCpyOptimizer.cpp MergeICmps.cpp Index: lib/Transforms/Scalar/LowerWidenableCondition.cpp =================================================================== --- /dev/null +++ lib/Transforms/Scalar/LowerWidenableCondition.cpp @@ -0,0 +1,86 @@ +//===- LowerWidenableCondition.cpp - Lower the guard intrinsic ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass lowers the llvm.widenable.condition intrinsic to default value +// which is i1 true. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar/LowerWidenableCondition.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/GuardUtils.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PatternMatch.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/GuardUtils.h" + +using namespace llvm; + +namespace { +struct LowerWidenableConditionLegacyPass : public FunctionPass { + static char ID; + LowerWidenableConditionLegacyPass() : FunctionPass(ID) { + initializeLowerWidenableConditionLegacyPassPass( + *PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override; +}; +} + +static bool lowerWidenableCondition(Function &F) { + // Check if we can cheaply rule out the possibility of not having any work to + // do. + auto *WCDecl = F.getParent()->getFunction( + Intrinsic::getName(Intrinsic::experimental_widenable_condition)); + if (!WCDecl || WCDecl->use_empty()) + return false; + + using namespace llvm::PatternMatch; + SmallVector ToLower; + for (auto &I : instructions(F)) + if (match(&I, m_Intrinsic())) + ToLower.push_back(cast(&I)); + + if (ToLower.empty()) + return false; + + for (auto *CI : ToLower) { + CI->replaceAllUsesWith(ConstantInt::getTrue(CI->getContext())); + CI->eraseFromParent(); + } + return true; +} + +bool LowerWidenableConditionLegacyPass::runOnFunction(Function &F) { + return lowerWidenableCondition(F); +} + +char LowerWidenableConditionLegacyPass::ID = 0; +INITIALIZE_PASS(LowerWidenableConditionLegacyPass, "lower-widenable-condition", + "Lower the widenable condition to default true value", false, + false) + +Pass *llvm::createLowerWidenableConditionPass() { + return new LowerWidenableConditionLegacyPass(); +} + +PreservedAnalyses LowerWidenableConditionPass::run(Function &F, + FunctionAnalysisManager &AM) { + if (lowerWidenableCondition(F)) + return PreservedAnalyses::none(); + + return PreservedAnalyses::all(); +} 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); + initializeLowerWidenableConditionLegacyPassPass(Registry); initializeMemCpyOptLegacyPassPass(Registry); initializeMergeICmpsPass(Registry); initializeMergedLoadStoreMotionLegacyPassPass(Registry); Index: test/Transforms/LowerWidenableCondition/basic.ll =================================================================== --- /dev/null +++ test/Transforms/LowerWidenableCondition/basic.ll @@ -0,0 +1,44 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -lower-widenable-condition < %s | FileCheck %s +; RUN: opt -S -passes=lower-widenable-condition < %s | FileCheck %s + +; Basic test case: make sure that all widenable conditions turn into i1 true. +define void @f_0(i1 %cond_0, i1 %cond_1) { +; CHECK-LABEL: @f_0( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], true +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]] +; CHECK: deopt: +; CHECK-NEXT: unreachable +; CHECK: guarded: +; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], true +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]] +; CHECK: deopt2: +; CHECK-NEXT: unreachable +; CHECK: guarded1: +; CHECK-NEXT: ret void +; +entry: + %widenable_cond = call i1 @llvm.experimental.widenable.condition() + %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond + br i1 %exiplicit_guard_cond, label %guarded, label %deopt + +deopt: ; preds = %entry + unreachable + +guarded: ; preds = %entry + %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() + %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 + br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2 + +deopt2: ; preds = %guarded + unreachable + +guarded1: ; preds = %guarded + ret void +} + +; Function Attrs: inaccessiblememonly nounwind +declare i1 @llvm.experimental.widenable.condition() #0 + +attributes #0 = { inaccessiblememonly nounwind }