Path: blob/main/contrib/llvm-project/llvm/lib/Target/X86/X86InsertWait.cpp
35266 views
//- X86Insertwait.cpp - Strict-Fp:Insert wait instruction X87 instructions --//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the pass which insert x86 wait instructions after each9// X87 instructions when strict float is enabled.10//11// The logic to insert a wait instruction after an X87 instruction is as below:12// 1. If the X87 instruction don't raise float exception nor is a load/store13// instruction, or is a x87 control instruction, don't insert wait.14// 2. If the X87 instruction is an instruction which the following instruction15// is an X87 exception synchronizing X87 instruction, don't insert wait.16// 3. For other situations, insert wait instruction.17//18//===----------------------------------------------------------------------===//1920#include "X86.h"21#include "X86InstrInfo.h"22#include "X86Subtarget.h"23#include "llvm/CodeGen/MachineBasicBlock.h"24#include "llvm/CodeGen/MachineFunction.h"25#include "llvm/CodeGen/MachineFunctionPass.h"26#include "llvm/CodeGen/MachineInstr.h"27#include "llvm/CodeGen/MachineInstrBuilder.h"28#include "llvm/CodeGen/MachineOperand.h"29#include "llvm/IR/DebugLoc.h"30#include "llvm/Support/Debug.h"3132using namespace llvm;3334#define DEBUG_TYPE "x86-insert-wait"3536namespace {3738class WaitInsert : public MachineFunctionPass {39public:40static char ID;4142WaitInsert() : MachineFunctionPass(ID) {}4344bool runOnMachineFunction(MachineFunction &MF) override;4546StringRef getPassName() const override {47return "X86 insert wait instruction";48}49};5051} // namespace5253char WaitInsert::ID = 0;5455FunctionPass *llvm::createX86InsertX87waitPass() { return new WaitInsert(); }5657static bool isX87ControlInstruction(MachineInstr &MI) {58switch (MI.getOpcode()) {59case X86::FNINIT:60case X86::FLDCW16m:61case X86::FNSTCW16m:62case X86::FNSTSW16r:63case X86::FNSTSWm:64case X86::FNCLEX:65case X86::FLDENVm:66case X86::FSTENVm:67case X86::FRSTORm:68case X86::FSAVEm:69case X86::FINCSTP:70case X86::FDECSTP:71case X86::FFREE:72case X86::FFREEP:73case X86::FNOP:74case X86::WAIT:75return true;76default:77return false;78}79}8081static bool isX87NonWaitingControlInstruction(MachineInstr &MI) {82// a few special control instructions don't perform a wait operation83switch (MI.getOpcode()) {84case X86::FNINIT:85case X86::FNSTSW16r:86case X86::FNSTSWm:87case X86::FNSTCW16m:88case X86::FNCLEX:89return true;90default:91return false;92}93}9495bool WaitInsert::runOnMachineFunction(MachineFunction &MF) {96if (!MF.getFunction().hasFnAttribute(Attribute::StrictFP))97return false;9899const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();100const X86InstrInfo *TII = ST.getInstrInfo();101bool Changed = false;102103for (MachineBasicBlock &MBB : MF) {104for (MachineBasicBlock::iterator MI = MBB.begin(); MI != MBB.end(); ++MI) {105// Jump non X87 instruction.106if (!X86::isX87Instruction(*MI))107continue;108// If the instruction instruction neither has float exception nor is109// a load/store instruction, or the instruction is x87 control110// instruction, do not insert wait.111if (!(MI->mayRaiseFPException() || MI->mayLoadOrStore()) ||112isX87ControlInstruction(*MI))113continue;114// If the following instruction is an X87 instruction and isn't an X87115// non-waiting control instruction, we can omit insert wait instruction.116MachineBasicBlock::iterator AfterMI = std::next(MI);117if (AfterMI != MBB.end() && X86::isX87Instruction(*AfterMI) &&118!isX87NonWaitingControlInstruction(*AfterMI))119continue;120121BuildMI(MBB, AfterMI, MI->getDebugLoc(), TII->get(X86::WAIT));122LLVM_DEBUG(dbgs() << "\nInsert wait after:\t" << *MI);123// Jump the newly inserting wait124++MI;125Changed = true;126}127}128return Changed;129}130131132