Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -812,6 +812,8 @@ GCCBuiltin<"__builtin_trap">; def int_debugtrap : Intrinsic<[]>, GCCBuiltin<"__builtin_debugtrap">; +def int_condtrap : Intrinsic<[], [], + [IntrReadMem, IntrWriteMem, IntrHasSideEffects]>; // Support for dynamic deoptimization (or de-specialization) def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], Index: lib/Target/ARM/ARM.h =================================================================== --- lib/Target/ARM/ARM.h +++ lib/Target/ARM/ARM.h @@ -37,6 +37,7 @@ FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM, CodeGenOpt::Level OptLevel); +FunctionPass *createARMCondTrapPass(); FunctionPass *createA15SDOptimizerPass(); FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); FunctionPass *createARMExpandPseudoPass(); Index: lib/Target/ARM/ARMCondTrapPass.cpp =================================================================== --- /dev/null +++ lib/Target/ARM/ARMCondTrapPass.cpp @@ -0,0 +1,102 @@ +//===-- ARMCondTrapPass - replaces cond traps with NOPs -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMSubtarget.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "arm-cond-trap" + +cl::opt + CondTrapToNop("arm-cond-trap-to-nop", cl::init(false), cl::Hidden); + +cl::opt + CondTrapToMov("arm-cond-trap-to-mov", cl::init(false), cl::Hidden); + +cl::opt + KeepCondTrapPred("arm-keep-cond-trap-pred", cl::init(false), cl::Hidden); + +namespace { +class ARMCondTrapPass : public MachineFunctionPass { +public: + static char ID; + ARMCondTrapPass() : MachineFunctionPass(ID), TII(nullptr) {} + + bool runOnMachineFunction(MachineFunction &Fn) override; + + StringRef getPassName() const override { return "cond trap pass"; } + +private: + bool updateCondTrapPredicates(MachineFunction &MF); + bool RunOnTrapBlock(MachineBasicBlock &TrapBB); + + const ARMBaseInstrInfo *TII; +}; +char ARMCondTrapPass::ID = 0; +} + +bool ARMCondTrapPass::updateCondTrapPredicates(MachineFunction &MF) { + unsigned long Changed = 0; + + for (auto &BB : MF) { + for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end();) { + MachineInstr &MI = *I; + ++I; + + if (MI.getOpcode() == ARM::CONDTRAP) { + ARMCC::CondCodes pred = + KeepCondTrapPred ? TII->getPredicate(MI) : ARMCC::AL; + if (CondTrapToNop) { + BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), TII->get(ARM::HINT)) + .addImm(0) + .add(predOps(pred)); + } else { + BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), TII->get(ARM::MOVr), + ARM::R0) + .addReg(ARM::R0) + .add(predOps(pred)) + .add(condCodeOp()); + } + MI.eraseFromParent(); + Changed++; + } + } + } + + if (Changed) + DEBUG(dbgs() << "Updated " << Changed << " conditional traps\n"); + + return Changed > 0; +} + +bool ARMCondTrapPass::runOnMachineFunction(MachineFunction &MF) { + if (!CondTrapToNop && !CondTrapToMov) + return false; + + TII = static_cast(MF.getSubtarget()).getInstrInfo(); + + DEBUG(dbgs() << "********** ARM Cond Trap **********\n" + << "********** Function: " << MF.getName() <<'\n'; + MF.dump()); + + return updateCondTrapPredicates(MF); +} + +FunctionPass *llvm::createARMCondTrapPass() { + return new ARMCondTrapPass(); +} Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -1997,6 +1997,13 @@ let DecoderMethod = "DecodeHINTInstruction"; } +def CONDTRAP : AI<(outs), (ins), MiscFrm, IIC_Br, "svc$p", "", + [(int_condtrap)]>, Requires<[IsARM]>, Sched<[WriteBr]> { + // SVCxx 0xFFFFFF + let Inst{27-24} = 0b1111; + let Inst{23-0} = 0b111111111111111111111111; +} + def : InstAlias<"nop$p", (HINT 0, pred:$p)>, Requires<[IsARM, HasV6K]>; def : InstAlias<"yield$p", (HINT 1, pred:$p)>, Requires<[IsARM, HasV6K]>; def : InstAlias<"wfe$p", (HINT 2, pred:$p)>, Requires<[IsARM, HasV6K]>; Index: lib/Target/ARM/ARMTargetMachine.cpp =================================================================== --- lib/Target/ARM/ARMTargetMachine.cpp +++ lib/Target/ARM/ARMTargetMachine.cpp @@ -356,6 +356,7 @@ void addPreRegAlloc() override; void addPreSched2() override; void addPreEmitPass() override; + void addPreEmitPass2() override; }; class ARMExecutionDomainFix : public ExecutionDomainFix { @@ -503,3 +504,7 @@ addPass(createARMConstantIslandPass()); } + +void ARMPassConfig::addPreEmitPass2() { + addPass(createARMCondTrapPass()); +} Index: lib/Target/ARM/CMakeLists.txt =================================================================== --- lib/Target/ARM/CMakeLists.txt +++ lib/Target/ARM/CMakeLists.txt @@ -54,6 +54,7 @@ Thumb2InstrInfo.cpp Thumb2SizeReduction.cpp ARMComputeBlockSize.cpp + ARMCondTrapPass.cpp ) add_subdirectory(AsmParser)