diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index c35159360e8a..8dad76b46a49 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -716,31 +716,37 @@ isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { const MachineOperand &MO = getOperand(DefOpIdx); if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) return false; - // Determine the actual operand no corresponding to this index. + // Determine the actual operand index that corresponds to this index. unsigned DefNo = 0; + unsigned DefPart = 0; for (unsigned i = 1, e = getNumOperands(); i < e; ) { const MachineOperand &FMO = getOperand(i); assert(FMO.isImm()); // Skip over this def. - i += InlineAsm::getNumOperandRegisters(FMO.getImm()) + 1; - if (i > DefOpIdx) + unsigned NumOps = InlineAsm::getNumOperandRegisters(FMO.getImm()); + unsigned PrevDef = i + 1; + i = PrevDef + NumOps; + if (i > DefOpIdx) { + DefPart = DefOpIdx - PrevDef; break; + } ++DefNo; } - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { const MachineOperand &FMO = getOperand(i); if (!FMO.isImm()) continue; if (i+1 >= e || !getOperand(i+1).isReg() || !getOperand(i+1).isUse()) continue; unsigned Idx; - if (InlineAsm::isUseOperandTiedToDef(FMO.getImm(), Idx) && + if (InlineAsm::isUseOperandTiedToDef(FMO.getImm(), Idx) && Idx == DefNo) { if (UseOpIdx) - *UseOpIdx = (unsigned)i + 1; + *UseOpIdx = (unsigned)i + 1 + DefPart; return true; } } + return false; } assert(getOperand(DefOpIdx).isDef() && "DefOpIdx is not a def!"); @@ -766,10 +772,16 @@ isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { const MachineOperand &MO = getOperand(UseOpIdx); if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0) return false; - assert(UseOpIdx > 0); - const MachineOperand &UFMO = getOperand(UseOpIdx-1); - if (!UFMO.isImm()) - return false; // Must be physreg uses. + int FlagIdx = UseOpIdx - 1; + if (FlagIdx < 1) + return false; + while (!getOperand(FlagIdx).isImm()) { + if (--FlagIdx == 0) + return false; + } + const MachineOperand &UFMO = getOperand(FlagIdx); + if (FlagIdx + InlineAsm::getNumOperandRegisters(UFMO.getImm()) < UseOpIdx) + return false; unsigned DefNo; if (InlineAsm::isUseOperandTiedToDef(UFMO.getImm(), DefNo)) { if (!DefOpIdx) @@ -785,7 +797,7 @@ isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { DefIdx += InlineAsm::getNumOperandRegisters(FMO.getImm()) + 1; --DefNo; } - *DefOpIdx = DefIdx+1; + *DefOpIdx = DefIdx + UseOpIdx - FlagIdx; return true; } return false; diff --git a/llvm/test/CodeGen/X86/inline-asm-tied.ll b/llvm/test/CodeGen/X86/inline-asm-tied.ll new file mode 100644 index 000000000000..6df2c48415bc --- /dev/null +++ b/llvm/test/CodeGen/X86/inline-asm-tied.ll @@ -0,0 +1,19 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 -O0 | grep {movl %edx, 4(%esp)} | count 2 +; rdar://6992609 + +target triple = "i386-apple-darwin9.0" +@llvm.used = appending global [1 x i8*] [i8* bitcast (i64 (i64)* @_OSSwapInt64 to i8*)], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0] + +define i64 @_OSSwapInt64(i64 %_data) nounwind { +entry: + %retval = alloca i64 ; [#uses=2] + %_data.addr = alloca i64 ; [#uses=4] + store i64 %_data, i64* %_data.addr + %tmp = load i64* %_data.addr ; [#uses=1] + %0 = call i64 asm "bswap %eax\0A\09bswap %edx\0A\09xchgl %eax, %edx", "=A,0,~{dirflag},~{fpsr},~{flags}"(i64 %tmp) nounwind ; [#uses=1] + store i64 %0, i64* %_data.addr + %tmp1 = load i64* %_data.addr ; [#uses=1] + store i64 %tmp1, i64* %retval + %1 = load i64* %retval ; [#uses=1] + ret i64 %1 +}