Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -4504,10 +4504,9 @@ ``unpredictable`` metadata may be attached to any branch or switch instruction. It can be used to express the unpredictability of control -flow. Similar to the llvm.expect intrinsic, it may be used to alter -optimizations related to compare and branch instructions. The metadata -is treated as a boolean value; if it exists, it signals that the branch -or switch that it is attached to is completely unpredictable. +flow and alter optimizations related to compare and branch instructions. +The metadata is treated as a boolean value; if it exists, it signals that +the branch or switch that it is attached to is completely unpredictable. '``llvm.loop``' ^^^^^^^^^^^^^^^ @@ -12034,39 +12033,6 @@ compile time, ``llvm.objectsize`` returns ``i32/i64 -1 or 0`` (depending on the ``min`` argument). -'``llvm.expect``' Intrinsic -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Syntax: -""""""" - -This is an overloaded intrinsic. You can use ``llvm.expect`` on any -integer bit width. - -:: - - declare i1 @llvm.expect.i1(i1 , i1 ) - declare i32 @llvm.expect.i32(i32 , i32 ) - declare i64 @llvm.expect.i64(i64 , i64 ) - -Overview: -""""""""" - -The ``llvm.expect`` intrinsic provides information about expected (the -most probable) value of ``val``, which can be used by optimizers. - -Arguments: -"""""""""" - -The ``llvm.expect`` intrinsic takes two arguments. The first argument is -a value. The second argument is an expected value, this needs to be a -constant value, variables are not allowed. - -Semantics: -"""""""""" - -This intrinsic is lowered to the ``val``. - .. _int_assume: '``llvm.assume``' Intrinsic Index: include/llvm-c/Transforms/Scalar.h =================================================================== --- include/llvm-c/Transforms/Scalar.h +++ include/llvm-c/Transforms/Scalar.h @@ -135,9 +135,6 @@ /** See llvm::createEarlyCSEPass function */ void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM); -/** See llvm::createLowerExpectIntrinsicPass function */ -void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM); - /** See llvm::createTypeBasedAliasAnalysisPass function */ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -410,11 +410,6 @@ [IntrNoMem]>, GCCBuiltin<"__builtin_object_size">; -//===------------------------- Expect Intrinsics --------------------------===// -// -def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, - LLVMMatchType<0>], [IntrNoMem]>; - //===-------------------- Bit Manipulation Intrinsics ---------------------===// // Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -187,7 +187,6 @@ void initializeLoopIdiomRecognizePass(PassRegistry&); void initializeLowerAtomicPass(PassRegistry&); void initializeLowerBitSetsPass(PassRegistry&); -void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerGuardIntrinsicPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokePass(PassRegistry&); Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -118,7 +118,6 @@ (void) llvm::createLoopVersioningLICMPass(); (void) llvm::createLoopIdiomPass(); (void) llvm::createLoopRotatePass(); - (void) llvm::createLowerExpectIntrinsicPass(); (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 @@ -392,12 +392,6 @@ //===----------------------------------------------------------------------===// // -// LowerExpectIntrinsics - Removes llvm.expect intrinsics and creates -// "block_weights" metadata. -FunctionPass *createLowerExpectIntrinsicPass(); - -//===----------------------------------------------------------------------===// -// // PartiallyInlineLibCalls - Tries to inline the fast path of library // calls such as sqrt. // Index: include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h =================================================================== --- include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h +++ include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h @@ -1,37 +0,0 @@ -//===- LowerExpectIntrinsic.h - LowerExpectIntrinsic pass -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// The header file for the LowerExpectIntrinsic pass as used by the new pass -/// manager. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H -#define LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H - -#include "llvm/IR/Function.h" -#include "llvm/IR/PassManager.h" - -namespace llvm { - -struct LowerExpectIntrinsicPass : PassInfoMixin { - /// \brief Run the pass over the function. - /// - /// This will lower all of th expect intrinsic calls in this function into - /// branch weight metadata. That metadata will subsequently feed the analysis - /// of the probabilities and frequencies of the CFG. After running this pass, - /// no more expect intrinsics remain, allowing the rest of the optimizer to - /// ignore them. - PreservedAnalyses run(Function &F); -}; - -} - -#endif Index: lib/CodeGen/IntrinsicLowering.cpp =================================================================== --- lib/CodeGen/IntrinsicLowering.cpp +++ lib/CodeGen/IntrinsicLowering.cpp @@ -353,13 +353,6 @@ report_fatal_error("Code generator does not support intrinsic function '"+ Callee->getName()+"'!"); - case Intrinsic::expect: { - // Just replace __builtin_expect(exp, c) with EXP. - Value *V = CI->getArgOperand(0); - CI->replaceAllUsesWith(V); - break; - } - // The setjmp/longjmp intrinsics should only exist in the code if it was // never optimized (ie, right out of the CFE), or if it has been hacked on // by the lowerinvoke pass. In both cases, the right thing to do is to Index: lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/FastISel.cpp +++ lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1225,13 +1225,6 @@ updateValueMap(II, ResultReg); return true; } - case Intrinsic::expect: { - unsigned ResultReg = getRegForValue(II->getArgOperand(0)); - if (!ResultReg) - return false; - updateValueMap(II, ResultReg); - return true; - } case Intrinsic::experimental_stackmap: return selectStackmap(II); case Intrinsic::experimental_patchpoint_void: Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5415,12 +5415,6 @@ setValue(&I, DAG.getNode(ISD::FLT_ROUNDS_, sdl, MVT::i32)); return nullptr; - case Intrinsic::expect: { - // Just replace __builtin_expect(exp, c) with EXP. - setValue(&I, getValue(I.getArgOperand(0))); - return nullptr; - } - case Intrinsic::debugtrap: case Intrinsic::trap: { StringRef TrapFuncName = Index: lib/IR/AutoUpgrade.cpp =================================================================== --- lib/IR/AutoUpgrade.cpp +++ lib/IR/AutoUpgrade.cpp @@ -145,6 +145,12 @@ break; } + case 'e': + if (Name.startswith("expect.") && F->arg_size() == 2) { + NewFn = nullptr; + return true; + } + case 'o': // We only need to change the name to match the mangling including the // address space. @@ -653,6 +659,11 @@ Rep = Builder.CreateShuffleVector(Op0, UndefV, ConstantVector::get(Idxs)); } else if (Name == "llvm.stackprotectorcheck") { Rep = nullptr; + } else if (Name.startswith("llvm.expect")) { + // The expect intrinsic always lowered to its first argument. + // TODO: We could create the appropriate metadata here to better support + // legacy code? + Rep = CI->getArgOperand(0); } else { bool PD128 = false, PD256 = false, PS128 = false, PS256 = false; if (Name == "llvm.x86.avx.vpermil.pd.256") Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -53,7 +53,6 @@ #include "llvm/Transforms/InstrProfiling.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" -#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/SROA.h" #include "llvm/Transforms/Scalar/SimplifyCFG.h" @@ -174,7 +173,6 @@ EarlyFPM.addPass(SimplifyCFGPass()); EarlyFPM.addPass(SROA()); EarlyFPM.addPass(EarlyCSEPass()); - EarlyFPM.addPass(LowerExpectIntrinsicPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(EarlyFPM))); } Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -100,7 +100,6 @@ FUNCTION_PASS("instcombine", InstCombinePass()) FUNCTION_PASS("invalidate", InvalidateAllAnalysesPass()) FUNCTION_PASS("no-op-function", NoOpFunctionPass()) -FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass()) FUNCTION_PASS("gvn", GVN()) FUNCTION_PASS("print", PrintFunctionPass(dbgs())) FUNCTION_PASS("print", AssumptionPrinterPass(dbgs())) Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -210,7 +210,6 @@ else FPM.add(createScalarReplAggregatesPass()); FPM.add(createEarlyCSEPass()); - FPM.add(createLowerExpectIntrinsicPass()); } // Do PGO instrumentation generation or use pass as the option specified. Index: lib/Transforms/Scalar/CMakeLists.txt =================================================================== --- lib/Transforms/Scalar/CMakeLists.txt +++ lib/Transforms/Scalar/CMakeLists.txt @@ -31,7 +31,6 @@ LoopUnswitch.cpp LoopVersioningLICM.cpp LowerAtomic.cpp - LowerExpectIntrinsic.cpp LowerGuardIntrinsic.cpp MemCpyOptimizer.cpp MergedLoadStoreMotion.cpp Index: lib/Transforms/Scalar/LowerExpectIntrinsic.cpp =================================================================== --- lib/Transforms/Scalar/LowerExpectIntrinsic.cpp +++ lib/Transforms/Scalar/LowerExpectIntrinsic.cpp @@ -1,192 +0,0 @@ -//===- LowerExpectIntrinsic.cpp - Lower expect 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 'expect' intrinsic to LLVM metadata. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Metadata.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Transforms/Scalar.h" - -using namespace llvm; - -#define DEBUG_TYPE "lower-expect-intrinsic" - -STATISTIC(ExpectIntrinsicsHandled, - "Number of 'expect' intrinsic instructions handled"); - -static cl::opt -LikelyBranchWeight("likely-branch-weight", cl::Hidden, cl::init(64), - cl::desc("Weight of the branch likely to be taken (default = 64)")); -static cl::opt -UnlikelyBranchWeight("unlikely-branch-weight", cl::Hidden, cl::init(4), - cl::desc("Weight of the branch unlikely to be taken (default = 4)")); - -static bool handleSwitchExpect(SwitchInst &SI) { - CallInst *CI = dyn_cast(SI.getCondition()); - if (!CI) - return false; - - Function *Fn = CI->getCalledFunction(); - if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) - return false; - - Value *ArgValue = CI->getArgOperand(0); - ConstantInt *ExpectedValue = dyn_cast(CI->getArgOperand(1)); - if (!ExpectedValue) - return false; - - SwitchInst::CaseIt Case = SI.findCaseValue(ExpectedValue); - unsigned n = SI.getNumCases(); // +1 for default case. - SmallVector Weights(n + 1, UnlikelyBranchWeight); - - if (Case == SI.case_default()) - Weights[0] = LikelyBranchWeight; - else - Weights[Case.getCaseIndex() + 1] = LikelyBranchWeight; - - SI.setMetadata(LLVMContext::MD_prof, - MDBuilder(CI->getContext()).createBranchWeights(Weights)); - - SI.setCondition(ArgValue); - return true; -} - -static bool handleBranchExpect(BranchInst &BI) { - if (BI.isUnconditional()) - return false; - - // Handle non-optimized IR code like: - // %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1) - // %tobool = icmp ne i64 %expval, 0 - // br i1 %tobool, label %if.then, label %if.end - // - // Or the following simpler case: - // %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1) - // br i1 %expval, label %if.then, label %if.end - - CallInst *CI; - - ICmpInst *CmpI = dyn_cast(BI.getCondition()); - if (!CmpI) { - CI = dyn_cast(BI.getCondition()); - } else { - if (CmpI->getPredicate() != CmpInst::ICMP_NE) - return false; - CI = dyn_cast(CmpI->getOperand(0)); - } - - if (!CI) - return false; - - Function *Fn = CI->getCalledFunction(); - if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) - return false; - - Value *ArgValue = CI->getArgOperand(0); - ConstantInt *ExpectedValue = dyn_cast(CI->getArgOperand(1)); - if (!ExpectedValue) - return false; - - MDBuilder MDB(CI->getContext()); - MDNode *Node; - - // If expect value is equal to 1 it means that we are more likely to take - // branch 0, in other case more likely is branch 1. - if (ExpectedValue->isOne()) - Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight); - else - Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight); - - BI.setMetadata(LLVMContext::MD_prof, Node); - - if (CmpI) - CmpI->setOperand(0, ArgValue); - else - BI.setCondition(ArgValue); - return true; -} - -static bool lowerExpectIntrinsic(Function &F) { - bool Changed = false; - - for (BasicBlock &BB : F) { - // Create "block_weights" metadata. - if (BranchInst *BI = dyn_cast(BB.getTerminator())) { - if (handleBranchExpect(*BI)) - ExpectIntrinsicsHandled++; - } else if (SwitchInst *SI = dyn_cast(BB.getTerminator())) { - if (handleSwitchExpect(*SI)) - ExpectIntrinsicsHandled++; - } - - // Remove llvm.expect intrinsics. - for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;) { - CallInst *CI = dyn_cast(BI++); - if (!CI) - continue; - - Function *Fn = CI->getCalledFunction(); - if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) { - Value *Exp = CI->getArgOperand(0); - CI->replaceAllUsesWith(Exp); - CI->eraseFromParent(); - Changed = true; - } - } - } - - return Changed; -} - -PreservedAnalyses LowerExpectIntrinsicPass::run(Function &F) { - if (lowerExpectIntrinsic(F)) - return PreservedAnalyses::none(); - - return PreservedAnalyses::all(); -} - -namespace { -/// \brief Legacy pass for lowering expect intrinsics out of the IR. -/// -/// When this pass is run over a function it uses expect intrinsics which feed -/// branches and switches to provide branch weight metadata for those -/// terminators. It then removes the expect intrinsics from the IR so the rest -/// of the optimizer can ignore them. -class LowerExpectIntrinsic : public FunctionPass { -public: - static char ID; - LowerExpectIntrinsic() : FunctionPass(ID) { - initializeLowerExpectIntrinsicPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F) override { return lowerExpectIntrinsic(F); } -}; -} - -char LowerExpectIntrinsic::ID = 0; -INITIALIZE_PASS(LowerExpectIntrinsic, "lower-expect", - "Lower 'expect' Intrinsics", false, false) - -FunctionPass *llvm::createLowerExpectIntrinsicPass() { - return new LowerExpectIntrinsic(); -} Index: lib/Transforms/Scalar/Scalar.cpp =================================================================== --- lib/Transforms/Scalar/Scalar.cpp +++ lib/Transforms/Scalar/Scalar.cpp @@ -61,7 +61,6 @@ initializeLoopVersioningLICMPass(Registry); initializeLoopIdiomRecognizePass(Registry); initializeLowerAtomicPass(Registry); - initializeLowerExpectIntrinsicPass(Registry); initializeLowerGuardIntrinsicPass(Registry); initializeMemCpyOptPass(Registry); initializeMergedLoadStoreMotionPass(Registry); @@ -248,7 +247,3 @@ void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createBasicAAWrapperPass()); } - -void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerExpectIntrinsicPass()); -} Index: test/Assembler/auto_upgrade_intrinsics.ll =================================================================== --- test/Assembler/auto_upgrade_intrinsics.ll +++ test/Assembler/auto_upgrade_intrinsics.ll @@ -68,6 +68,24 @@ ret void } +define i32 @test_expect(i32 %x) { +; CHECK-LABEL: @test_expect( +; CHECK: %tobool = icmp ne i32 %x, 0 + +entry: + %expval = call i32 @llvm.expect.i32(i32 %x, i32 1) + %tobool = icmp ne i32 %expval, 0 + br i1 %tobool, label %if, label %else + +if: + ret i32 54321 + +else: + ret i32 12345 +} + +declare i32 @llvm.expect.i32(i32, i32) nounwind readnone + ; This is part of @test.objectsize(), since llvm.objectsize declaration gets ; emitted at the end. ; CHECK: declare i32 @llvm.objectsize.i32.p0i8 Index: test/CodeGen/Generic/builtin-expect.ll =================================================================== --- test/CodeGen/Generic/builtin-expect.ll +++ test/CodeGen/Generic/builtin-expect.ll @@ -1,223 +0,0 @@ -; RUN: llc < %s - -define i32 @test1(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %cmp = icmp sgt i32 %tmp, 1 - %conv = zext i1 %cmp to i32 - %conv1 = sext i32 %conv to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1) - %tobool = icmp ne i64 %expval, 0 - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -declare i64 @llvm.expect.i64(i64, i64) nounwind readnone - -declare i32 @f(...) - -define i32 @test2(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %conv = sext i32 %tmp to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - %tobool = icmp ne i64 %expval, 0 - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -define i32 @test3(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %tobool = icmp ne i32 %tmp, 0 - %lnot = xor i1 %tobool, true - %lnot.ext = zext i1 %lnot to i32 - %conv = sext i32 %lnot.ext to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - %tobool1 = icmp ne i64 %expval, 0 - br i1 %tobool1, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -define i32 @test4(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %tobool = icmp ne i32 %tmp, 0 - %lnot = xor i1 %tobool, true - %lnot1 = xor i1 %lnot, true - %lnot.ext = zext i1 %lnot1 to i32 - %conv = sext i32 %lnot.ext to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - %tobool2 = icmp ne i64 %expval, 0 - br i1 %tobool2, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -define i32 @test5(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %cmp = icmp slt i32 %tmp, 0 - %conv = zext i1 %cmp to i32 - %conv1 = sext i32 %conv to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 0) - %tobool = icmp ne i64 %expval, 0 - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -define i32 @test6(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %conv = sext i32 %tmp to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - switch i64 %expval, label %sw.epilog [ - i64 1, label %sw.bb - i64 2, label %sw.bb - ] - -sw.bb: ; preds = %entry, %entry - store i32 0, i32* %retval - br label %return - -sw.epilog: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %sw.epilog, %sw.bb - %0 = load i32, i32* %retval - ret i32 %0 -} - -define i32 @test7(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %conv = sext i32 %tmp to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - switch i64 %expval, label %sw.epilog [ - i64 2, label %sw.bb - i64 3, label %sw.bb - ] - -sw.bb: ; preds = %entry, %entry - %tmp1 = load i32, i32* %x.addr, align 4 - store i32 %tmp1, i32* %retval - br label %return - -sw.epilog: ; preds = %entry - store i32 0, i32* %retval - br label %return - -return: ; preds = %sw.epilog, %sw.bb - %0 = load i32, i32* %retval - ret i32 %0 -} - -define i32 @test8(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %cmp = icmp sgt i32 %tmp, 1 - %conv = zext i1 %cmp to i32 - %expval = call i32 @llvm.expect.i32(i32 %conv, i32 1) - %tobool = icmp ne i32 %expval, 0 - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -declare i32 @llvm.expect.i32(i32, i32) nounwind readnone - Index: test/Other/new-pass-manager.ll =================================================================== --- test/Other/new-pass-manager.ll +++ test/Other/new-pass-manager.ll @@ -353,7 +353,6 @@ ; CHECK-O2: Running pass: SimplifyCFGPass ; CHECK-O2: Running pass: SROA ; CHECK-O2: Running pass: EarlyCSEPass -; CHECK-O2: Running pass: LowerExpectIntrinsicPass ; RUN: opt -disable-output -disable-verify -debug-pass-manager \ ; RUN: -passes='lto' %s 2>&1 \ Index: test/Transforms/LowerExpectIntrinsic/basic.ll =================================================================== --- test/Transforms/LowerExpectIntrinsic/basic.ll +++ test/Transforms/LowerExpectIntrinsic/basic.ll @@ -1,281 +0,0 @@ -; RUN: opt -lower-expect -strip-dead-prototypes -S -o - < %s | FileCheck %s -; RUN: opt -S -passes='function(lower-expect),strip-dead-prototypes' < %s | FileCheck %s - -; CHECK-LABEL: @test1( -define i32 @test1(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %cmp = icmp sgt i32 %tmp, 1 - %conv = zext i1 %cmp to i32 - %conv1 = sext i32 %conv to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1) - %tobool = icmp ne i64 %expval, 0 -; CHECK: !prof !0 -; CHECK-NOT: @llvm.expect - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -declare i64 @llvm.expect.i64(i64, i64) nounwind readnone - -declare i32 @f(...) - -; CHECK-LABEL: @test2( -define i32 @test2(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %conv = sext i32 %tmp to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - %tobool = icmp ne i64 %expval, 0 -; CHECK: !prof !0 -; CHECK-NOT: @llvm.expect - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -; CHECK-LABEL: @test3( -define i32 @test3(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %tobool = icmp ne i32 %tmp, 0 - %lnot = xor i1 %tobool, true - %lnot.ext = zext i1 %lnot to i32 - %conv = sext i32 %lnot.ext to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - %tobool1 = icmp ne i64 %expval, 0 -; CHECK: !prof !0 -; CHECK-NOT: @llvm.expect - br i1 %tobool1, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -; CHECK-LABEL: @test4( -define i32 @test4(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %tobool = icmp ne i32 %tmp, 0 - %lnot = xor i1 %tobool, true - %lnot1 = xor i1 %lnot, true - %lnot.ext = zext i1 %lnot1 to i32 - %conv = sext i32 %lnot.ext to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) - %tobool2 = icmp ne i64 %expval, 0 -; CHECK: !prof !0 -; CHECK-NOT: @llvm.expect - br i1 %tobool2, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -; CHECK-LABEL: @test5( -define i32 @test5(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %cmp = icmp slt i32 %tmp, 0 - %conv = zext i1 %cmp to i32 - %conv1 = sext i32 %conv to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 0) - %tobool = icmp ne i64 %expval, 0 -; CHECK: !prof !1 -; CHECK-NOT: @llvm.expect - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -; CHECK-LABEL: @test6( -define i32 @test6(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %conv = sext i32 %tmp to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) -; CHECK: !prof !2 -; CHECK-NOT: @llvm.expect - switch i64 %expval, label %sw.epilog [ - i64 1, label %sw.bb - i64 2, label %sw.bb - ] - -sw.bb: ; preds = %entry, %entry - store i32 0, i32* %retval - br label %return - -sw.epilog: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %sw.epilog, %sw.bb - %0 = load i32, i32* %retval - ret i32 %0 -} - -; CHECK-LABEL: @test7( -define i32 @test7(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %conv = sext i32 %tmp to i64 - %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1) -; CHECK: !prof !3 -; CHECK-NOT: @llvm.expect - switch i64 %expval, label %sw.epilog [ - i64 2, label %sw.bb - i64 3, label %sw.bb - ] - -sw.bb: ; preds = %entry, %entry - %tmp1 = load i32, i32* %x.addr, align 4 - store i32 %tmp1, i32* %retval - br label %return - -sw.epilog: ; preds = %entry - store i32 0, i32* %retval - br label %return - -return: ; preds = %sw.epilog, %sw.bb - %0 = load i32, i32* %retval - ret i32 %0 -} - -; CHECK-LABEL: @test8( -define i32 @test8(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %cmp = icmp sgt i32 %tmp, 1 - %conv = zext i1 %cmp to i32 - %expval = call i32 @llvm.expect.i32(i32 %conv, i32 1) - %tobool = icmp ne i32 %expval, 0 -; CHECK: !prof !0 -; CHECK-NOT: @llvm.expect - br i1 %tobool, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -declare i32 @llvm.expect.i32(i32, i32) nounwind readnone - -; CHECK-LABEL: @test9( -define i32 @test9(i32 %x) nounwind uwtable ssp { -entry: - %retval = alloca i32, align 4 - %x.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4 - %cmp = icmp sgt i32 %tmp, 1 - %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1) -; CHECK: !prof !0 -; CHECK-NOT: @llvm.expect - br i1 %expval, label %if.then, label %if.end - -if.then: ; preds = %entry - %call = call i32 (...) @f() - store i32 %call, i32* %retval - br label %return - -if.end: ; preds = %entry - store i32 1, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %0 = load i32, i32* %retval - ret i32 %0 -} - -declare i1 @llvm.expect.i1(i1, i1) nounwind readnone - -; CHECK: !0 = !{!"branch_weights", i32 64, i32 4} -; CHECK: !1 = !{!"branch_weights", i32 4, i32 64} -; CHECK: !2 = !{!"branch_weights", i32 4, i32 64, i32 4} -; CHECK: !3 = !{!"branch_weights", i32 64, i32 4, i32 4}