X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTarget%2FX86%2FX86MCInstLower.cpp;h=4e0d594238c2ef09bed5961876b489354e03e779;hp=9fa171ce4d512a1830af37ec10e2d780735dd8ff;hb=68aeef61f4a1da7af53b6ddcdbb6eb75da7eb72d;hpb=30e89dd88295f710f1cd3880cb721f6e9c0ed8b7 diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 9fa171ce4d5..4e0d594238c 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -75,10 +75,10 @@ namespace llvm { void X86AsmPrinter::StackMapShadowTracker::startFunction(MachineFunction &MF) { - CodeEmitter.reset(TM.getTarget().createMCCodeEmitter(*TM.getInstrInfo(), - *TM.getRegisterInfo(), - *TM.getSubtargetImpl(), - MF.getContext())); + CodeEmitter.reset(TM.getTarget().createMCCodeEmitter( + *TM.getSubtargetImpl()->getInstrInfo(), + *TM.getSubtargetImpl()->getRegisterInfo(), *TM.getSubtargetImpl(), + MF.getContext())); } void X86AsmPrinter::StackMapShadowTracker::count(MCInst &Inst, @@ -124,7 +124,7 @@ MachineModuleInfoMachO &X86MCInstLower::getMachOMMI() const { /// operand to an MCSymbol. MCSymbol *X86MCInstLower:: GetSymbolFromOperand(const MachineOperand &MO) const { - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) && "Isn't a symbol reference"); SmallString<128> Name; @@ -264,7 +264,8 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO, Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(MF.getPICBaseSymbol(), Ctx), Ctx); - if (MO.isJTI() && MAI.hasSetDirective()) { + if (MO.isJTI()) { + assert(MAI.doesSetDirectiveSuppressesReloc()); // If .set directive is supported, use it to reduce the number of // relocations the assembler will generate for differences between // local labels. This is only safe when the symbols are in the same @@ -583,14 +584,38 @@ ReSimplify: // Atomic load and store require a separate pseudo-inst because Acquire // implies mayStore and Release implies mayLoad; fix these to regular MOV // instructions here - case X86::ACQUIRE_MOV8rm: OutMI.setOpcode(X86::MOV8rm); goto ReSimplify; - case X86::ACQUIRE_MOV16rm: OutMI.setOpcode(X86::MOV16rm); goto ReSimplify; - case X86::ACQUIRE_MOV32rm: OutMI.setOpcode(X86::MOV32rm); goto ReSimplify; - case X86::ACQUIRE_MOV64rm: OutMI.setOpcode(X86::MOV64rm); goto ReSimplify; - case X86::RELEASE_MOV8mr: OutMI.setOpcode(X86::MOV8mr); goto ReSimplify; - case X86::RELEASE_MOV16mr: OutMI.setOpcode(X86::MOV16mr); goto ReSimplify; - case X86::RELEASE_MOV32mr: OutMI.setOpcode(X86::MOV32mr); goto ReSimplify; - case X86::RELEASE_MOV64mr: OutMI.setOpcode(X86::MOV64mr); goto ReSimplify; + case X86::ACQUIRE_MOV8rm: OutMI.setOpcode(X86::MOV8rm); goto ReSimplify; + case X86::ACQUIRE_MOV16rm: OutMI.setOpcode(X86::MOV16rm); goto ReSimplify; + case X86::ACQUIRE_MOV32rm: OutMI.setOpcode(X86::MOV32rm); goto ReSimplify; + case X86::ACQUIRE_MOV64rm: OutMI.setOpcode(X86::MOV64rm); goto ReSimplify; + case X86::RELEASE_MOV8mr: OutMI.setOpcode(X86::MOV8mr); goto ReSimplify; + case X86::RELEASE_MOV16mr: OutMI.setOpcode(X86::MOV16mr); goto ReSimplify; + case X86::RELEASE_MOV32mr: OutMI.setOpcode(X86::MOV32mr); goto ReSimplify; + case X86::RELEASE_MOV64mr: OutMI.setOpcode(X86::MOV64mr); goto ReSimplify; + case X86::RELEASE_MOV8mi: OutMI.setOpcode(X86::MOV8mi); goto ReSimplify; + case X86::RELEASE_MOV16mi: OutMI.setOpcode(X86::MOV16mi); goto ReSimplify; + case X86::RELEASE_MOV32mi: OutMI.setOpcode(X86::MOV32mi); goto ReSimplify; + case X86::RELEASE_MOV64mi32: OutMI.setOpcode(X86::MOV64mi32); goto ReSimplify; + case X86::RELEASE_ADD8mi: OutMI.setOpcode(X86::ADD8mi); goto ReSimplify; + case X86::RELEASE_ADD32mi: OutMI.setOpcode(X86::ADD32mi); goto ReSimplify; + case X86::RELEASE_ADD64mi32: OutMI.setOpcode(X86::ADD64mi32); goto ReSimplify; + case X86::RELEASE_AND8mi: OutMI.setOpcode(X86::AND8mi); goto ReSimplify; + case X86::RELEASE_AND32mi: OutMI.setOpcode(X86::AND32mi); goto ReSimplify; + case X86::RELEASE_AND64mi32: OutMI.setOpcode(X86::AND64mi32); goto ReSimplify; + case X86::RELEASE_OR8mi: OutMI.setOpcode(X86::OR8mi); goto ReSimplify; + case X86::RELEASE_OR32mi: OutMI.setOpcode(X86::OR32mi); goto ReSimplify; + case X86::RELEASE_OR64mi32: OutMI.setOpcode(X86::OR64mi32); goto ReSimplify; + case X86::RELEASE_XOR8mi: OutMI.setOpcode(X86::XOR8mi); goto ReSimplify; + case X86::RELEASE_XOR32mi: OutMI.setOpcode(X86::XOR32mi); goto ReSimplify; + case X86::RELEASE_XOR64mi32: OutMI.setOpcode(X86::XOR64mi32); goto ReSimplify; + case X86::RELEASE_INC8m: OutMI.setOpcode(X86::INC8m); goto ReSimplify; + case X86::RELEASE_INC16m: OutMI.setOpcode(X86::INC16m); goto ReSimplify; + case X86::RELEASE_INC32m: OutMI.setOpcode(X86::INC32m); goto ReSimplify; + case X86::RELEASE_INC64m: OutMI.setOpcode(X86::INC64m); goto ReSimplify; + case X86::RELEASE_DEC8m: OutMI.setOpcode(X86::DEC8m); goto ReSimplify; + case X86::RELEASE_DEC16m: OutMI.setOpcode(X86::DEC16m); goto ReSimplify; + case X86::RELEASE_DEC32m: OutMI.setOpcode(X86::DEC32m); goto ReSimplify; + case X86::RELEASE_DEC64m: OutMI.setOpcode(X86::DEC64m); goto ReSimplify; // We don't currently select the correct instruction form for instructions // which have a short %eax, etc. form. Handle this by custom lowering, for @@ -826,10 +851,98 @@ void X86AsmPrinter::LowerPATCHPOINT(const MachineInstr &MI) { getSubtargetInfo()); } +// Returns instruction preceding MBBI in MachineFunction. +// If MBBI is the first instruction of the first basic block, returns null. +static MachineBasicBlock::const_iterator +PrevCrossBBInst(MachineBasicBlock::const_iterator MBBI) { + const MachineBasicBlock *MBB = MBBI->getParent(); + while (MBBI == MBB->begin()) { + if (MBB == MBB->getParent()->begin()) + return nullptr; + MBB = MBB->getPrevNode(); + MBBI = MBB->end(); + } + return --MBBI; +} + +static const Constant *getConstantFromPool(const MachineInstr &MI, + const MachineOperand &Op) { + if (!Op.isCPI()) + return nullptr; + + ArrayRef Constants = + MI.getParent()->getParent()->getConstantPool()->getConstants(); + const MachineConstantPoolEntry &ConstantEntry = + Constants[Op.getIndex()]; + + // Bail if this is a machine constant pool entry, we won't be able to dig out + // anything useful. + if (ConstantEntry.isMachineConstantPoolEntry()) + return nullptr; + + auto *C = dyn_cast(ConstantEntry.Val.ConstVal); + assert((!C || ConstantEntry.getType() == C->getType()) && + "Expected a constant of the same type!"); + return C; +} + +static std::string getShuffleComment(const MachineOperand &DstOp, + const MachineOperand &SrcOp, + ArrayRef Mask) { + std::string Comment; + + // Compute the name for a register. This is really goofy because we have + // multiple instruction printers that could (in theory) use different + // names. Fortunately most people use the ATT style (outside of Windows) + // and they actually agree on register naming here. Ultimately, this is + // a comment, and so its OK if it isn't perfect. + auto GetRegisterName = [](unsigned RegNum) -> StringRef { + return X86ATTInstPrinter::getRegisterName(RegNum); + }; + + StringRef DstName = DstOp.isReg() ? GetRegisterName(DstOp.getReg()) : "mem"; + StringRef SrcName = SrcOp.isReg() ? GetRegisterName(SrcOp.getReg()) : "mem"; + + raw_string_ostream CS(Comment); + CS << DstName << " = "; + bool NeedComma = false; + bool InSrc = false; + for (int M : Mask) { + // Wrap up any prior entry... + if (M == SM_SentinelZero && InSrc) { + InSrc = false; + CS << "]"; + } + if (NeedComma) + CS << ","; + else + NeedComma = true; + + // Print this shuffle... + if (M == SM_SentinelZero) { + CS << "zero"; + } else { + if (!InSrc) { + InSrc = true; + CS << SrcName << "["; + } + if (M == SM_SentinelUndef) + CS << "u"; + else + CS << M; + } + } + if (InSrc) + CS << "]"; + CS.flush(); + + return Comment; +} + void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { X86MCInstLower MCInstLowering(*MF, *this); - const X86RegisterInfo *RI = - static_cast(TM.getRegisterInfo()); + const X86RegisterInfo *RI = static_cast( + TM.getSubtargetImpl()->getRegisterInfo()); switch (MI->getOpcode()) { case TargetOpcode::DBG_VALUE: @@ -967,85 +1080,150 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitWinCFIEndProlog(); return; + case X86::SEH_Epilogue: { + MachineBasicBlock::const_iterator MBBI(MI); + // Check if preceded by a call and emit nop if so. + for (MBBI = PrevCrossBBInst(MBBI); MBBI; MBBI = PrevCrossBBInst(MBBI)) { + // Conservatively assume that pseudo instructions don't emit code and keep + // looking for a call. We may emit an unnecessary nop in some cases. + if (!MBBI->isPseudo()) { + if (MBBI->isCall()) + EmitAndCountInstruction(MCInstBuilder(X86::NOOP)); + break; + } + } + return; + } + + // Lower PSHUFB and VPERMILP normally but add a comment if we can find + // a constant shuffle mask. We won't be able to do this at the MC layer + // because the mask isn't an immediate. case X86::PSHUFBrm: - // Lower PSHUFB normally but add a comment if we can find a constant - // shuffle mask. We won't be able to do this at the MC layer because the - // mask isn't an immediate. - std::string Comment; - raw_string_ostream CS(Comment); - SmallVector Mask; - - assert(MI->getNumOperands() == 7 && - "Wrong number of operansd for PSHUFBrm"); + case X86::VPSHUFBrm: + case X86::VPSHUFBYrm: { + if (!OutStreamer.isVerboseAsm()) + break; + assert(MI->getNumOperands() > 5 && + "We should always have at least 5 operands!"); const MachineOperand &DstOp = MI->getOperand(0); const MachineOperand &SrcOp = MI->getOperand(1); const MachineOperand &MaskOp = MI->getOperand(5); - // Compute the name for a register. This is really goofy because we have - // multiple instruction printers that could (in theory) use different - // names. Fortunately most people use the ATT style (outside of Windows) - // and they actually agree on register naming here. Ultimately, this is - // a comment, and so its OK if it isn't perfect. - auto GetRegisterName = [](unsigned RegNum) -> StringRef { - return X86ATTInstPrinter::getRegisterName(RegNum); - }; - - StringRef DstName = DstOp.isReg() ? GetRegisterName(DstOp.getReg()) : "mem"; - StringRef SrcName = SrcOp.isReg() ? GetRegisterName(SrcOp.getReg()) : "mem"; - CS << DstName << " = "; - - if (MaskOp.isCPI()) { - ArrayRef Constants = - MI->getParent()->getParent()->getConstantPool()->getConstants(); - const MachineConstantPoolEntry &MaskConstantEntry = - Constants[MI->getOperand(5).getIndex()]; - Type *MaskTy = MaskConstantEntry.getType(); - if (!MaskConstantEntry.isMachineConstantPoolEntry()) - if (auto *C = dyn_cast( - MaskConstantEntry.Val.ConstVal)) { - assert(MaskTy == C->getType() && - "Expected a constant of the same type!"); - - DecodePSHUFBMask(C, Mask); - assert(Mask.size() == MaskTy->getVectorNumElements() && - "Shuffle mask has a different size than its type!"); - } + if (auto *C = getConstantFromPool(*MI, MaskOp)) { + SmallVector Mask; + DecodePSHUFBMask(C, Mask); + if (!Mask.empty()) + OutStreamer.AddComment(getShuffleComment(DstOp, SrcOp, Mask)); + } + break; + } + case X86::VPERMILPSrm: + case X86::VPERMILPDrm: + case X86::VPERMILPSYrm: + case X86::VPERMILPDYrm: { + if (!OutStreamer.isVerboseAsm()) + break; + assert(MI->getNumOperands() > 5 && + "We should always have at least 5 operands!"); + const MachineOperand &DstOp = MI->getOperand(0); + const MachineOperand &SrcOp = MI->getOperand(1); + const MachineOperand &MaskOp = MI->getOperand(5); + + if (auto *C = getConstantFromPool(*MI, MaskOp)) { + SmallVector Mask; + DecodeVPERMILPMask(C, Mask); + if (!Mask.empty()) + OutStreamer.AddComment(getShuffleComment(DstOp, SrcOp, Mask)); } + break; + } - if (!Mask.empty()) { - bool NeedComma = false; - bool InSrc = false; - for (int M : Mask) { - // Wrap up any prior entry... - if (M == SM_SentinelZero && InSrc) { - InSrc = false; - CS << "]"; + // For loads from a constant pool to a vector register, print the constant + // loaded. + case X86::MOVAPDrm: + case X86::VMOVAPDrm: + case X86::VMOVAPDYrm: + case X86::MOVUPDrm: + case X86::VMOVUPDrm: + case X86::VMOVUPDYrm: + case X86::MOVAPSrm: + case X86::VMOVAPSrm: + case X86::VMOVAPSYrm: + case X86::MOVUPSrm: + case X86::VMOVUPSrm: + case X86::VMOVUPSYrm: + case X86::MOVDQArm: + case X86::VMOVDQArm: + case X86::VMOVDQAYrm: + case X86::MOVDQUrm: + case X86::VMOVDQUrm: + case X86::VMOVDQUYrm: + if (!OutStreamer.isVerboseAsm()) + break; + if (MI->getNumOperands() > 4) + if (auto *C = getConstantFromPool(*MI, MI->getOperand(4))) { + std::string Comment; + raw_string_ostream CS(Comment); + const MachineOperand &DstOp = MI->getOperand(0); + CS << X86ATTInstPrinter::getRegisterName(DstOp.getReg()) << " = "; + if (auto *CDS = dyn_cast(C)) { + CS << "["; + for (int i = 0, NumElements = CDS->getNumElements(); i < NumElements; ++i) { + if (i != 0) + CS << ","; + if (CDS->getElementType()->isIntegerTy()) + CS << CDS->getElementAsInteger(i); + else if (CDS->getElementType()->isFloatTy()) + CS << CDS->getElementAsFloat(i); + else if (CDS->getElementType()->isDoubleTy()) + CS << CDS->getElementAsDouble(i); + else + CS << "?"; } - if (NeedComma) - CS << ","; - else - NeedComma = true; - - // Print this shuffle... - if (M == SM_SentinelZero) { - CS << "zero"; - } else { - if (!InSrc) { - InSrc = true; - CS << SrcName << "["; + CS << "]"; + OutStreamer.AddComment(CS.str()); + } else if (auto *CV = dyn_cast(C)) { + CS << "<"; + for (int i = 0, NumOperands = CV->getNumOperands(); i < NumOperands; ++i) { + if (i != 0) + CS << ","; + Constant *COp = CV->getOperand(i); + if (isa(COp)) { + CS << "u"; + } else if (auto *CI = dyn_cast(COp)) { + CS << CI->getZExtValue(); + } else if (auto *CF = dyn_cast(COp)) { + SmallString<32> Str; + CF->getValueAPF().toString(Str); + CS << Str; + } else { + CS << "?"; } - CS << M; } + CS << ">"; + OutStreamer.AddComment(CS.str()); } - if (InSrc) - CS << "]"; - - OutStreamer.AddComment(CS.str()); } break; } MCInst TmpInst; MCInstLowering.Lower(MI, TmpInst); + + // Stackmap shadows cannot include branch targets, so we can count the bytes + // in a call towards the shadow, but must ensure that the no thread returns + // in to the stackmap shadow. The only way to achieve this is if the call + // is at the end of the shadow. + if (MI->isCall()) { + // Count then size of the call towards the shadow + SMShadowTracker.count(TmpInst, getSubtargetInfo()); + // Then flush the shadow so that we fill with nops before the call, not + // after it. + SMShadowTracker.emitShadowPadding(OutStreamer, getSubtargetInfo()); + // Then emit the call + OutStreamer.EmitInstruction(TmpInst, getSubtargetInfo()); + return; + } + EmitAndCountInstruction(TmpInst); }