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 @@ -231,6 +231,12 @@ return Val_unit; } +/* [ 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); 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/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 @@ -395,6 +395,13 @@ // "block_weights" metadata. FunctionPass *createLowerExpectIntrinsicPass(); +//===----------------------------------------------------------------------===// +// +// LowerIsConstantIntrinsics - Converts llvm.is.constant intrinsics into 'true' +// or 'false'. +// +FunctionPass *createLowerIsConstantIntrinsicPass(bool Final = false); + //===----------------------------------------------------------------------===// // // PartiallyInlineLibCalls - Tries to inline the fast path of library Index: include/llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h =================================================================== --- /dev/null +++ include/llvm/Transforms/Scalar/LowerIsConstantIntrinsic.h @@ -0,0 +1,41 @@ +//===- 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 { +private: + bool Final; +public: + explicit LowerIsConstantIntrinsicPass(bool Final = false) + : Final(Final) {} + + /// Run the pass over the function. + /// + /// This will lower all of the 'is.constant'` intrinsic calls in this function + /// into 'true' or 'false'. We want to resolve to 'true' as early as possible + /// and 'false' as late as possible. + PreservedAnalyses run(Function &F, FunctionAnalysisManager &); +}; + +} + +#endif Index: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -430,8 +430,13 @@ if (Modifier[0] == 'l') { // Labels are target independent. if (MI->getOperand(OpNo).isBlockAddress()) { const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress(); - MCSymbol *Sym = AP->GetBlockAddressSymbol(BA); - Sym->print(OS, AP->MAI); + const BasicBlock *BB = BA->getBasicBlock(); + const MachineFunction *MF = MI->getParent()->getParent(); + for (const MachineBasicBlock &MBB : *MF) + if (BB == MBB.getBasicBlock()) { + MBB.getSymbol()->print(OS, AP->MAI); + break; + } } else if (MI->getOperand(OpNo).isMBB()) { const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol(); Sym->print(OS, AP->MAI); 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 =================================================================== --- /dev/null +++ lib/Transforms/Scalar/LowerIsConstantIntrinsic.cpp @@ -0,0 +1,112 @@ +//===- 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/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, bool Final) { + Value *Op = II->getOperand(0); + Value *Exp = nullptr; + + if (isa(Op)) + Exp = ConstantInt::getTrue(II->getType()); + else if (Final) + Exp = ConstantInt::getFalse(II->getType()); + + if (Exp) { + II->replaceAllUsesWith(Exp); + II->eraseFromParent(); + return true; + } + + return false; +} + +static bool lowerIsConstantIntrinsic(Function &F, bool Final, + const TargetLibraryInfo *TLI) { + bool Changed = false; + + for (BasicBlock &BB : F) { + bool Handled = false; + 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; + Handled |= handleIsConstantIntrinsic(II, Final); + IsConstantIntrinsicsHandled++; + } + } + Changed |= Handled && SimplifyInstructionsInBlock(&BB, TLI); + } + + return Changed; +} + +PreservedAnalyses LowerIsConstantIntrinsicPass::run( + Function &F, FunctionAnalysisManager &AM) { + if (lowerIsConstantIntrinsic(F, Final, + 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'. We want to convert to 'true' as early in the +/// pipeline as possible and 'false' as late as possible. +class LowerIsConstantIntrinsic : public FunctionPass { + bool Final; +public: + static char ID; + LowerIsConstantIntrinsic(bool Final = false) + : FunctionPass(ID), Final(Final) { + initializeLowerIsConstantIntrinsicPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + auto *TLIP = getAnalysisIfAvailable(); + const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI() : nullptr; + return lowerIsConstantIntrinsic(F, Final, TLI); + } +}; +} + +char LowerIsConstantIntrinsic::ID = 0; +INITIALIZE_PASS(LowerIsConstantIntrinsic, "lower-is-constant", + "Lower 'is.constant' Intrinsics", false, false) + +FunctionPass *llvm::createLowerIsConstantIntrinsicPass(bool Final) { + return new LowerIsConstantIntrinsic(Final); +} 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/X86/callbr-asm-obj-file.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/callbr-asm-obj-file.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -mtriple=x86_64-linux-gnu -filetype=obj -o - \ +; RUN: | llvm-objdump -triple x86_64-linux-gnu -d - \ +; RUN: | FileCheck %s + +; CHECK: 0000000000000000 test1: +; CHECK-NEXT: 0: 74 00 je 0 +; CHECK-NEXT: 2: c3 retq + +define void @test1() { +entry: + callbr void asm sideeffect "je ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %a.b.normal.jump)) + to label %asm.fallthrough [label %a.b.normal.jump] + +asm.fallthrough: + ret void + +a.b.normal.jump: + ret void +} Index: test/CodeGen/X86/callbr-asm.ll =================================================================== --- test/CodeGen/X86/callbr-asm.ll +++ test/CodeGen/X86/callbr-asm.ll @@ -12,7 +12,7 @@ ; CHECK-NEXT: addl $4, %eax ; CHECK-NEXT: #APP ; CHECK-NEXT: xorl %eax, %eax -; CHECK-NEXT: jmp .Ltmp00 +; CHECK-NEXT: jmp .LBB0_2 ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: .LBB0_1: # %normal ; CHECK-NEXT: xorl %eax, %eax @@ -87,17 +87,17 @@ ; CHECK-NEXT: # Parent Loop BB2_3 Depth=3 ; CHECK-NEXT: # => This Inner Loop Header: Depth=4 ; CHECK-NEXT: #APP -; CHECK-NEXT: jmp .Ltmp10 -; CHECK-NEXT: jmp .Ltmp20 -; CHECK-NEXT: jmp .Ltmp30 +; CHECK-NEXT: jmp .LBB2_1 +; CHECK-NEXT: jmp .LBB2_2 +; CHECK-NEXT: jmp .LBB2_3 ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: .LBB2_5: # %normal0 ; CHECK-NEXT: # in Loop: Header=BB2_4 Depth=4 ; CHECK-NEXT: #APP -; CHECK-NEXT: jmp .Ltmp10 -; CHECK-NEXT: jmp .Ltmp20 -; CHECK-NEXT: jmp .Ltmp30 -; CHECK-NEXT: jmp .Ltmp40 +; CHECK-NEXT: jmp .LBB2_1 +; CHECK-NEXT: jmp .LBB2_2 +; CHECK-NEXT: jmp .LBB2_3 +; CHECK-NEXT: jmp .LBB2_4 ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: .LBB2_6: # %normal1 ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 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",