1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

Do not model all INLINEASM instructions as having unmodelled side effects.

Instead encode llvm IR level property "HasSideEffects" in an operand (shared
with IsAlignStack). Added MachineInstrs::hasUnmodeledSideEffects() to check
the operand when the instruction is an INLINEASM.

This allows memory instructions to be moved around INLINEASM instructions.

llvm-svn: 123044
This commit is contained in:
Evan Cheng 2011-01-07 23:50:32 +00:00
parent 4e879f0f00
commit aa16fd02ad
21 changed files with 129 additions and 46 deletions

View File

@ -482,7 +482,7 @@ namespace ISD {
// Operand #0 : Input chain. // Operand #0 : Input chain.
// Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string.
// Operand #2 : a MDNodeSDNode with the !srcloc metadata. // Operand #2 : a MDNodeSDNode with the !srcloc metadata.
// Operand #3 : IsAlignStack bit. // Operand #3 : HasSideEffect, IsAlignStack bits.
// After this, it is followed by a list of operands with this format: // After this, it is followed by a list of operands with this format:
// ConstantSDNode: Flags that encode whether it is a mem or not, the // ConstantSDNode: Flags that encode whether it is a mem or not, the
// of operands that follow, etc. See InlineAsm.h. // of operands that follow, etc. See InlineAsm.h.

View File

@ -237,6 +237,7 @@ public:
bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isKill() const { return getOpcode() == TargetOpcode::KILL; }
bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; } bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; }
bool isStackAligningInlineAsm() const;
bool isInsertSubreg() const { bool isInsertSubreg() const {
return getOpcode() == TargetOpcode::INSERT_SUBREG; return getOpcode() == TargetOpcode::INSERT_SUBREG;
} }
@ -432,6 +433,15 @@ public:
/// return 0. /// return 0.
unsigned isConstantValuePHI() const; unsigned isConstantValuePHI() const;
/// hasUnmodeledSideEffects - Return true if this instruction has side
/// effects that are not modeled by mayLoad / mayStore, etc.
/// For all instructions, the property is encoded in TargetInstrDesc::Flags
/// (see TargetInstrDesc::hasUnmodeledSideEffects(). The only exception is
/// INLINEASM instruction, in which case the side effect property is encoded
/// in one of its operands (see InlineAsm::Extra_HasSideEffect).
///
bool hasUnmodeledSideEffects() const;
/// allDefsAreDead - Return true if all the defs of this instruction are dead. /// allDefsAreDead - Return true if all the defs of this instruction are dead.
/// ///
bool allDefsAreDead() const; bool allDefsAreDead() const;

View File

@ -190,9 +190,16 @@ public:
Op_InputChain = 0, Op_InputChain = 0,
Op_AsmString = 1, Op_AsmString = 1,
Op_MDNode = 2, Op_MDNode = 2,
Op_IsAlignStack = 3, Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack
Op_FirstOperand = 4, Op_FirstOperand = 4,
MIOp_AsmString = 0,
MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack
MIOp_FirstOperand = 2,
Extra_HasSideEffects = 1,
Extra_IsAlignStack = 2,
Kind_RegUse = 1, Kind_RegUse = 1,
Kind_RegDef = 2, Kind_RegDef = 2,
Kind_Imm = 3, Kind_Imm = 3,

View File

@ -418,6 +418,7 @@ def INLINEASM : Instruction {
let OutOperandList = (outs); let OutOperandList = (outs);
let InOperandList = (ins variable_ops); let InOperandList = (ins variable_ops);
let AsmString = ""; let AsmString = "";
let neverHasSideEffects = 1; // Note side effect is encoded in an operand.
} }
def PROLOG_LABEL : Instruction { def PROLOG_LABEL : Instruction {
let OutOperandList = (outs); let OutOperandList = (outs);

View File

@ -304,7 +304,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
// Okay, we finally have a value number. Ask the target to print this // Okay, we finally have a value number. Ask the target to print this
// operand! // operand!
if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
unsigned OpNo = 2; unsigned OpNo = InlineAsm::MIOp_FirstOperand;
bool Error = false; bool Error = false;

View File

@ -54,6 +54,12 @@ FunctionPass *llvm::createDeadMachineInstructionElimPass() {
} }
bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const {
// Technically speaking inline asm without side effects and no defs can still
// be deleted. But there is so much bad inline asm code out there, we should
// let them be.
if (MI->isInlineAsm())
return false;
// Don't delete instructions with side effects. // Don't delete instructions with side effects.
bool SawStore = false; bool SawStore = false;
if (!MI->isSafeToMove(TII, 0, SawStore) && !MI->isPHI()) if (!MI->isSafeToMove(TII, 0, SawStore) && !MI->isPHI())

View File

@ -262,7 +262,7 @@ bool MachineCSE::isCSECandidate(MachineInstr *MI) {
// Ignore stuff that we obviously can't move. // Ignore stuff that we obviously can't move.
const TargetInstrDesc &TID = MI->getDesc(); const TargetInstrDesc &TID = MI->getDesc();
if (TID.mayStore() || TID.isCall() || TID.isTerminator() || if (TID.mayStore() || TID.isCall() || TID.isTerminator() ||
TID.hasUnmodeledSideEffects()) MI->hasUnmodeledSideEffects())
return false; return false;
if (TID.mayLoad()) { if (TID.mayLoad()) {

View File

@ -826,6 +826,14 @@ unsigned MachineInstr::getNumExplicitOperands() const {
return NumOperands; return NumOperands;
} }
bool MachineInstr::isStackAligningInlineAsm() const {
if (isInlineAsm()) {
unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
return true;
}
return false;
}
/// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of /// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of
/// the specific register or -1 if it is not found. It further tightens /// the specific register or -1 if it is not found. It further tightens
@ -925,14 +933,15 @@ int MachineInstr::findFirstPredOperandIdx() const {
bool MachineInstr:: bool MachineInstr::
isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const {
if (isInlineAsm()) { if (isInlineAsm()) {
assert(DefOpIdx >= 3); assert(DefOpIdx > InlineAsm::MIOp_FirstOperand);
const MachineOperand &MO = getOperand(DefOpIdx); const MachineOperand &MO = getOperand(DefOpIdx);
if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0)
return false; return false;
// Determine the actual operand index that corresponds to this index. // Determine the actual operand index that corresponds to this index.
unsigned DefNo = 0; unsigned DefNo = 0;
unsigned DefPart = 0; unsigned DefPart = 0;
for (unsigned i = 2, e = getNumOperands(); i < e; ) { for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands();
i < e; ) {
const MachineOperand &FMO = getOperand(i); const MachineOperand &FMO = getOperand(i);
// After the normal asm operands there may be additional imp-def regs. // After the normal asm operands there may be additional imp-def regs.
if (!FMO.isImm()) if (!FMO.isImm())
@ -947,7 +956,8 @@ isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const {
} }
++DefNo; ++DefNo;
} }
for (unsigned i = 2, e = getNumOperands(); i != e; ++i) { for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands();
i != e; ++i) {
const MachineOperand &FMO = getOperand(i); const MachineOperand &FMO = getOperand(i);
if (!FMO.isImm()) if (!FMO.isImm())
continue; continue;
@ -990,7 +1000,8 @@ isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const {
// Find the flag operand corresponding to UseOpIdx // Find the flag operand corresponding to UseOpIdx
unsigned FlagIdx, NumOps=0; unsigned FlagIdx, NumOps=0;
for (FlagIdx = 2; FlagIdx < UseOpIdx; FlagIdx += NumOps+1) { for (FlagIdx = InlineAsm::MIOp_FirstOperand;
FlagIdx < UseOpIdx; FlagIdx += NumOps+1) {
const MachineOperand &UFMO = getOperand(FlagIdx); const MachineOperand &UFMO = getOperand(FlagIdx);
// After the normal asm operands there may be additional imp-def regs. // After the normal asm operands there may be additional imp-def regs.
if (!UFMO.isImm()) if (!UFMO.isImm())
@ -1008,9 +1019,9 @@ isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const {
if (!DefOpIdx) if (!DefOpIdx)
return true; return true;
unsigned DefIdx = 2; unsigned DefIdx = InlineAsm::MIOp_FirstOperand;
// Remember to adjust the index. First operand is asm string, second is // Remember to adjust the index. First operand is asm string, second is
// the AlignStack bit, then there is a flag for each. // the HasSideEffects and AlignStack bits, then there is a flag for each.
while (DefNo) { while (DefNo) {
const MachineOperand &FMO = getOperand(DefIdx); const MachineOperand &FMO = getOperand(DefIdx);
assert(FMO.isImm()); assert(FMO.isImm());
@ -1117,7 +1128,7 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII,
} }
if (isLabel() || isDebugValue() || if (isLabel() || isDebugValue() ||
TID->isTerminator() || TID->hasUnmodeledSideEffects()) TID->isTerminator() || hasUnmodeledSideEffects())
return false; return false;
// See if this instruction does a load. If so, we have to guarantee that the // See if this instruction does a load. If so, we have to guarantee that the
@ -1168,7 +1179,7 @@ bool MachineInstr::hasVolatileMemoryRef() const {
if (!TID->mayStore() && if (!TID->mayStore() &&
!TID->mayLoad() && !TID->mayLoad() &&
!TID->isCall() && !TID->isCall() &&
!TID->hasUnmodeledSideEffects()) !hasUnmodeledSideEffects())
return false; return false;
// Otherwise, if the instruction has no memory reference information, // Otherwise, if the instruction has no memory reference information,
@ -1242,6 +1253,18 @@ unsigned MachineInstr::isConstantValuePHI() const {
return Reg; return Reg;
} }
bool MachineInstr::hasUnmodeledSideEffects() const {
if (getDesc().hasUnmodeledSideEffects())
return true;
if (isInlineAsm()) {
unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
return true;
}
return false;
}
/// allDefsAreDead - Return true if all the defs of this instruction are dead. /// allDefsAreDead - Return true if all the defs of this instruction are dead.
/// ///
bool MachineInstr::allDefsAreDead() const { bool MachineInstr::allDefsAreDead() const {
@ -1329,6 +1352,24 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
// Print the rest of the operands. // Print the rest of the operands.
bool OmittedAnyCallClobbers = false; bool OmittedAnyCallClobbers = false;
bool FirstOp = true; bool FirstOp = true;
if (isInlineAsm()) {
// Print asm string.
OS << " ";
getOperand(InlineAsm::MIOp_AsmString).print(OS, TM);
// Print HasSideEffects, IsAlignStack
unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
OS << " [sideeffect]";
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
OS << " [alignstack]";
StartOp = InlineAsm::MIOp_FirstOperand;
FirstOp = false;
}
for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) { for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) {
const MachineOperand &MO = getOperand(i); const MachineOperand &MO = getOperand(i);

View File

@ -338,7 +338,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
if (MI->isLabel() || MI->isPHI() || MI->isImplicitDef() || if (MI->isLabel() || MI->isPHI() || MI->isImplicitDef() ||
MI->isKill() || MI->isInlineAsm() || MI->isDebugValue() || MI->isKill() || MI->isInlineAsm() || MI->isDebugValue() ||
MI->getDesc().hasUnmodeledSideEffects()) MI->hasUnmodeledSideEffects())
continue; continue;
if (MI->getDesc().isCompare()) { if (MI->getDesc().isCompare()) {

View File

@ -21,6 +21,7 @@
#define DEBUG_TYPE "pei" #define DEBUG_TYPE "pei"
#include "PrologEpilogInserter.h" #include "PrologEpilogInserter.h"
#include "llvm/InlineAsm.h"
#include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstr.h"
@ -172,7 +173,8 @@ void PEI::calculateCallsInformation(MachineFunction &Fn) {
FrameSDOps.push_back(I); FrameSDOps.push_back(I);
} else if (I->isInlineAsm()) { } else if (I->isInlineAsm()) {
// Some inline asm's need a stack frame, as indicated by operand 1. // Some inline asm's need a stack frame, as indicated by operand 1.
if (I->getOperand(1).getImm()) unsigned ExtraInfo = I->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
AdjustsStack = true; AdjustsStack = true;
} }

View File

@ -410,7 +410,7 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) {
// produce more precise dependence information. // produce more precise dependence information.
#define STORE_LOAD_LATENCY 1 #define STORE_LOAD_LATENCY 1
unsigned TrueMemOrderLatency = 0; unsigned TrueMemOrderLatency = 0;
if (TID.isCall() || TID.hasUnmodeledSideEffects() || if (TID.isCall() || MI->hasUnmodeledSideEffects() ||
(MI->hasVolatileMemoryRef() && (MI->hasVolatileMemoryRef() &&
(!TID.mayLoad() || !MI->isInvariantLoad(AA)))) { (!TID.mayLoad() || !MI->isInvariantLoad(AA)))) {
// Be conservative with these and add dependencies on all memory // Be conservative with these and add dependencies on all memory

View File

@ -821,11 +821,11 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
const char *AsmStr = cast<ExternalSymbolSDNode>(AsmStrV)->getSymbol(); const char *AsmStr = cast<ExternalSymbolSDNode>(AsmStrV)->getSymbol();
MI->addOperand(MachineOperand::CreateES(AsmStr)); MI->addOperand(MachineOperand::CreateES(AsmStr));
// Add the isAlignStack bit. // Add the HasSideEffect and isAlignStack bits.
int64_t isAlignStack = int64_t ExtraInfo =
cast<ConstantSDNode>(Node->getOperand(InlineAsm::Op_IsAlignStack))-> cast<ConstantSDNode>(Node->getOperand(InlineAsm::Op_ExtraInfo))->
getZExtValue(); getZExtValue();
MI->addOperand(MachineOperand::CreateImm(isAlignStack)); MI->addOperand(MachineOperand::CreateImm(ExtraInfo));
// Add all of the operand registers to the instruction. // Add all of the operand registers to the instruction.
for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {

View File

@ -5738,9 +5738,14 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
const MDNode *SrcLoc = CS.getInstruction()->getMetadata("srcloc"); const MDNode *SrcLoc = CS.getInstruction()->getMetadata("srcloc");
AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc)); AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc));
// Remember the AlignStack bit as operand 3. // Remember the HasSideEffect and AlignStack bits as operand 3.
AsmNodeOperands.push_back(DAG.getTargetConstant(IA->isAlignStack() ? 1 : 0, unsigned ExtraInfo = 0;
MVT::i1)); if (IA->hasSideEffects())
ExtraInfo |= InlineAsm::Extra_HasSideEffects;
if (IA->isAlignStack())
ExtraInfo |= InlineAsm::Extra_IsAlignStack;
AsmNodeOperands.push_back(DAG.getTargetConstant(ExtraInfo,
TLI.getPointerTy()));
// Loop over all of the inputs, copying the operand values into the // Loop over all of the inputs, copying the operand values into the
// appropriate registers and processing the output regs. // appropriate registers and processing the output regs.

View File

@ -380,10 +380,8 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
II = MBB->begin(), IE = MBB->end(); II != IE; ++II) { II = MBB->begin(), IE = MBB->end(); II != IE; ++II) {
const TargetInstrDesc &TID = TM.getInstrInfo()->get(II->getOpcode()); const TargetInstrDesc &TID = TM.getInstrInfo()->get(II->getOpcode());
// Operand 1 of an inline asm instruction indicates whether the asm if ((TID.isCall() && !TID.isReturn()) ||
// needs stack or not. II->isStackAligningInlineAsm()) {
if ((II->isInlineAsm() && II->getOperand(1).getImm()) ||
(TID.isCall() && !TID.isReturn())) {
MFI->setHasCalls(true); MFI->setHasCalls(true);
goto done; goto done;
} }
@ -1283,7 +1281,7 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
Ops.push_back(InOps[InlineAsm::Op_InputChain]); // 0 Ops.push_back(InOps[InlineAsm::Op_InputChain]); // 0
Ops.push_back(InOps[InlineAsm::Op_AsmString]); // 1 Ops.push_back(InOps[InlineAsm::Op_AsmString]); // 1
Ops.push_back(InOps[InlineAsm::Op_MDNode]); // 2, !srcloc Ops.push_back(InOps[InlineAsm::Op_MDNode]); // 2, !srcloc
Ops.push_back(InOps[InlineAsm::Op_IsAlignStack]); // 3 Ops.push_back(InOps[InlineAsm::Op_ExtraInfo]); // 3 (SideEffect, AlignStack)
unsigned i = InlineAsm::Op_FirstOperand, e = InOps.size(); unsigned i = InlineAsm::Op_FirstOperand, e = InOps.size();
if (InOps[e-1].getValueType() == MVT::Glue) if (InOps[e-1].getValueType() == MVT::Glue)

View File

@ -329,8 +329,13 @@ isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI,
const TargetInstrDesc &TID = MI->getDesc(); const TargetInstrDesc &TID = MI->getDesc();
// Avoid instructions obviously unsafe for remat. // Avoid instructions obviously unsafe for remat.
if (TID.hasUnmodeledSideEffects() || TID.isNotDuplicable() || if (TID.isNotDuplicable() || TID.mayStore() ||
TID.mayStore()) MI->hasUnmodeledSideEffects())
return false;
// Don't remat inline asm. We have no idea how expensive it is
// even if it's side effect free.
if (MI->isInlineAsm())
return false; return false;
// Avoid instructions which load from potentially varying memory. // Avoid instructions which load from potentially varying memory.

View File

@ -743,7 +743,7 @@ static bool isSafeToDelete(MachineInstr *MI,
const TargetInstrDesc &TID = MI->getDesc(); const TargetInstrDesc &TID = MI->getDesc();
if (TID.mayStore() || TID.isCall()) if (TID.mayStore() || TID.isCall())
return false; return false;
if (TID.isTerminator() || TID.hasUnmodeledSideEffects()) if (TID.isTerminator() || MI->hasUnmodeledSideEffects())
return false; return false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {

View File

@ -1620,9 +1620,16 @@ static bool isSafeToDelete(MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc(); const TargetInstrDesc &TID = MI.getDesc();
if (TID.mayLoad() || TID.mayStore() || TID.isCall() || TID.isTerminator() || if (TID.mayLoad() || TID.mayStore() || TID.isCall() || TID.isTerminator() ||
TID.isCall() || TID.isBarrier() || TID.isReturn() || TID.isCall() || TID.isBarrier() || TID.isReturn() ||
TID.hasUnmodeledSideEffects() || MI.isLabel() || MI.isDebugValue() ||
MI.isLabel() || MI.isDebugValue()) MI.hasUnmodeledSideEffects())
return false; return false;
// Technically speaking inline asm without side effects and no defs can still
// be deleted. But there is so much bad inline asm code out there, we should
// let them be.
if (MI.isInlineAsm())
return false;
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i); MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || !MO.getReg()) if (!MO.isReg() || !MO.getReg())

View File

@ -1467,7 +1467,7 @@ static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base,
if (I->isDebugValue() || MemOps.count(&*I)) if (I->isDebugValue() || MemOps.count(&*I))
continue; continue;
const TargetInstrDesc &TID = I->getDesc(); const TargetInstrDesc &TID = I->getDesc();
if (TID.isCall() || TID.isTerminator() || TID.hasUnmodeledSideEffects()) if (TID.isCall() || TID.isTerminator() || I->hasUnmodeledSideEffects())
return false; return false;
if (isLd && TID.mayStore()) if (isLd && TID.mayStore())
return false; return false;

View File

@ -187,9 +187,8 @@ static bool isDelayFiller(MachineBasicBlock &MBB,
return (brdesc.hasDelaySlot()); return (brdesc.hasDelaySlot());
} }
static bool hasUnknownSideEffects(MachineBasicBlock::iterator &I, static bool hasUnknownSideEffects(MachineBasicBlock::iterator &I) {
TargetInstrDesc &desc) { if (!I->hasUnmodeledSideEffects())
if (!desc.hasUnmodeledSideEffects())
return false; return false;
unsigned op = I->getOpcode(); unsigned op = I->getOpcode();
@ -215,7 +214,7 @@ findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) {
TargetInstrDesc desc = I->getDesc(); TargetInstrDesc desc = I->getDesc();
if (desc.hasDelaySlot() || desc.isBranch() || isDelayFiller(MBB,I) || if (desc.hasDelaySlot() || desc.isBranch() || isDelayFiller(MBB,I) ||
desc.isCall() || desc.isReturn() || desc.isBarrier() || desc.isCall() || desc.isReturn() || desc.isBarrier() ||
hasUnknownSideEffects(I,desc)) hasUnknownSideEffects(I))
break; break;
if (hasImmInstruction(I) || delayHasHazard(I,slot)) if (hasImmInstruction(I) || delayHasHazard(I,slot))

View File

@ -1036,8 +1036,8 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) {
} }
const TargetInstrDesc &TID = MI.getDesc(); const TargetInstrDesc &TID = MI.getDesc();
if (TID.hasUnmodeledSideEffects() || if (TID.hasImplicitDefOfPhysReg(X86::EFLAGS) ||
TID.hasImplicitDefOfPhysReg(X86::EFLAGS)) MI.hasUnmodeledSideEffects())
break; break;
} }

View File

@ -15,14 +15,16 @@
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin8" target triple = "i386-apple-darwin8"
@x = common global i32 0 ; <i32*> [#uses=1] @x = common global i32 0
define i32 @aci(i32* %pw) nounwind { define i32 @aci(i32* %pw) nounwind {
entry: entry:
%0 = load i32* @x, align 4 ; <i32> [#uses=1] %0 = load i32* @x, align 4
%asmtmp = tail call { i32, i32 } asm "movl $0, %eax\0A\090:\0A\09test %eax, %eax\0A\09je 1f\0A\09movl %eax, $2\0A\09incl $2\0A\09lock\0A\09cmpxchgl $2, $0\0A\09jne 0b\0A\091:", "=*m,=&{ax},=&r,*m,~{dirflag},~{fpsr},~{flags},~{memory},~{cc}"(i32* %pw, i32* %pw) nounwind ; <{ i32, i32 }> [#uses=0] %asmtmp = tail call { i32, i32 } asm "movl $0, %eax\0A\090:\0A\09test %eax, %eax\0A\09je 1f\0A\09movl %eax, $2\0A\09incl $2\0A\09lock\0A\09cmpxchgl $2, $0\0A\09jne 0b\0A\091:", "=*m,=&{ax},=&r,*m,~{dirflag},~{fpsr},~{flags},~{memory},~{cc}"(i32* %pw, i32* %pw) nounwind
%asmtmp2 = tail call { i32, i32 } asm "movl $0, %edx\0A\090:\0A\09test %edx, %edx\0A\09je 1f\0A\09movl %edx, $2\0A\09incl $2\0A\09lock\0A\09cmpxchgl $2, $0\0A\09jne 0b\0A\091:", "=*m,=&{dx},=&r,*m,~{dirflag},~{fpsr},~{flags},~{memory},~{cc}"(i32* %pw, i32* %pw) nounwind ; <{ i32, i32 }> [#uses=1] %asmtmp2 = tail call { i32, i32 } asm "movl $0, %edx\0A\090:\0A\09test %edx, %edx\0A\09je 1f\0A\09movl %edx, $2\0A\09incl $2\0A\09lock\0A\09cmpxchgl $2, $0\0A\09jne 0b\0A\091:", "=*m,=&{dx},=&r,*m,~{dirflag},~{fpsr},~{flags},~{memory},~{cc}"(i32* %pw, i32* %pw) nounwind
%asmresult3 = extractvalue { i32, i32 } %asmtmp2, 0 ; <i32> [#uses=1] %asmresult2 = extractvalue { i32, i32 } %asmtmp, 0
%1 = add i32 %asmresult3, %0 ; <i32> [#uses=1] %asmresult3 = extractvalue { i32, i32 } %asmtmp2, 0
ret i32 %1 %1 = add i32 %asmresult2, %asmresult3
%2 = add i32 %0, %1
ret i32 %2
} }