Inserting MachineInstr's

Hi,

I have a task to complete and I’m getting stuck. I can’t find anything comparable in the documentation. The shortest explanation I can give is as follows: I need to use double-precision floating point values for floating-point multiplies. I’ll not go into why: That would take the discussion away from the essential problem. E.g.

Replace:

fmuls %f20,%f21,%f8

with the sequence:

fstod %f20,%f0

fstod %f21,%f2

fmuld %f0,%f2,%f8

This is for a Sparc derived back-end and I’m already at the MachineInstr phase. The essential code I have now is as follows, but it doesn’t work. I’ve had much larger pieces of code, but I believe my mistake lies somewhere in here. I’m not sure if I’m heading down the right path with this. Please, any help would be appreciated – or any reference to an example, even better.

[code is iterating through the MachineBasicBlock – this code is pretty straightforward and you can probably guess what’s in it]

if (Opcode == SP::FMULS)

{

MachineOperand& MO = MI.getOperand(0);

DebugLoc DL = MBBI->getDebugLoc();

BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD), MO.getReg());

[ Then we’d do the second fstod and the fmuld, but I’ve not included this because the basic problem of generating the MachineInstr has happened already for this first MachineInstr]

MI.eraseFromParent();

}

Chris Dewhurst,

University of Limerick, Ireland

Hi,

I have a task to complete and I’m getting stuck. I can’t find anything comparable in the documentation. The shortest explanation I can give is as follows: I need to use double-precision floating point values for floating-point multiplies. I’ll not go into why: That would take the discussion away from the essential problem. E.g.

  Replace:

  fmuls %f20,%f21,%f8

  with the sequence:

  fstod %f20,%f0
  fstod %f21,%f2
  fmuld %f0,%f2,%f8

This is for a Sparc derived back-end and I’m already at the MachineInstr phase. The essential code I have now is as follows, but it doesn’t work. I’ve had much larger pieces of code, but I believe my mistake lies somewhere in here. I’m not sure if I’m heading down the right path with this. Please, any help would be appreciated – or any reference to an example, even better.

[code is iterating through the MachineBasicBlock – this code is pretty straightforward and you can probably guess what’s in it]
    if (Opcode == SP::FMULS)
      {
        MachineOperand& MO = MI.getOperand(0);
        DebugLoc DL = MBBI->getDebugLoc();
        BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD), MO.getReg());

Looks like this MI will write to the final destination register (%f8 in your example), which is not what you want IIUC.

You need to create a new register for the double (%f0) using:

    const TargetRegisterClass *DoubleRC = ….
    unsigned f0 = MRI.createVirtualRegister(DoubleRC);
    unsigned f2 = MRI.createVirtualRegister(DoubleRC);

And then you can try to build your sequence with something that will look like:

        BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD), f0).addReg(MI.getOperand(1).getReg());
        BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD), ).addReg(MI.getOperand(2).getReg());
        BuildMI(MBB, MBBI, DL, TII.get(FMULD), MO.getReg()).addReg(f0).addReg(f2);

           [ Then we’d do the second fstod and the fmuld, but I’ve not included this because the basic problem of generating the MachineInstr has happened already for this first MachineInstr]

(You haven’t really described what problem you have though).

Hi,

Just for completeness, the essential problem is that the hardware implementation of the Sparc-derived processor's FMULS operation is faulty and this needs to be fixed by substituting a FMULD to simulate the operation instead (FMULD does not exhibit the problem). The hardware fix will take a long time to be released.

More specifically, in terms of the running the code, the problem appear on the next iteration of the MBB, giving me this error, which could perhaps be because I've broken the list in MBB, perhaps??? The top line here doesn't give me many clues, but perhaps other will recognise it.

UNKNOWN %noreg, %noreg, [TF=2176], [TF=16], [TF=2188], %noreg, %noreg, %noreg, %noreg:sub(2213)<imp-def,tied9>, , , %noreg, [TF=2312], %physreg4, %noreg, [TF=2174], %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, %noreg, <BB#-4>, %noreg, %noreg, [TF=2183], %noreg, %noreg, %noreg, %noreg, %noreg, #0 0x21da6dc llvm::sys::PrintStackTrace(llvm::raw_ostream&) /home/chris/llvmbase/llvm/lib/Support/Unix/Signals.inc:437:0
#1 0x21daa58 PrintStackTraceSignalHandler(void*) /home/chris/llvmbase/llvm/lib/Support/Unix/Signals.inc:495:0
#2 0x21d957e SignalHandler(int) /home/chris/llvmbase/llvm/lib/Support/Unix/Signals.inc:210:0
#3 0x7ffff79b8130 __restore_rt (/lib64/libpthread.so.0+0xf130)
#4 0xc2e82c llvm::APInt::isSingleWord() const /home/chris/llvmbase/llvm/include/llvm/ADT/APInt.h:103:0
#5 0xd51284 llvm::APInt::operator==(unsigned long) const /home/chris/llvmbase/llvm/include/llvm/ADT/APInt.h:991:0
#6 0x21a0ed0 llvm::APInt::toString(llvm::SmallVectorImpl<char>&, unsigned int, bool, bool) const /home/chris/llvmbase/llvm/lib/Support/APInt.cpp:2171:0
#7 0x21a15cc llvm::APInt::print(llvm::raw_ostream&, bool) const /home/chris/llvmbase/llvm/lib/Support/APInt.cpp:2282:0
#8 0x19f837f llvm::MachineOperand::print(llvm::raw_ostream&, llvm::TargetRegisterInfo const*) const /home/chris/llvmbase/llvm/lib/CodeGen/MachineInstr.cpp:362:0
#9 0x19fd25d llvm::MachineInstr::print(llvm::raw_ostream&, bool) const /home/chris/llvmbase/llvm/lib/CodeGen/MachineInstr.cpp:1599:0
#10 0x1497872 ReplaceFMULS::runOnMachineFunction(llvm::MachineFunction&) /home/chris/llvmbase/llvm/lib/Target/Sparc/LeonPasses.cpp:113:0
#11 0x19f648d llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/chris/llvmbase/llvm/lib/CodeGen/MachineFunctionPass.cpp:41:0
#12 0x211c9d0 llvm::FPPassManager::runOnFunction(llvm::Function&) /home/chris/llvmbase/llvm/lib/IR/LegacyPassManager.cpp:1537:0
#13 0x211cb40 llvm::FPPassManager::runOnModule(llvm::Module&) /home/chris/llvmbase/llvm/lib/IR/LegacyPassManager.cpp:1557:0
#14 0x211ce94 (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /home/chris/llvmbase/llvm/lib/IR/LegacyPassManager.cpp:1615:0
#15 0x211d542 llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/chris/llvmbase/llvm/lib/IR/LegacyPassManager.cpp:1722:0
#16 0x211d761 llvm::legacy::PassManager::run(llvm::Module&) /home/chris/llvmbase/llvm/lib/IR/LegacyPassManager.cpp:1756:0
#17 0xc148e4 compileModule(char**, llvm::LLVMContext&) /home/chris/llvmbase/llvm/tools/llc/llc.cpp:362:0
#18 0xc139f6 main /home/chris/llvmbase/llvm/tools/llc/llc.cpp:204:0
#19 0x7ffff69bcaf5 __libc_start_main /usr/src/debug/glibc-2.17-c758a686/csu/libc-start.c:308:0
#20 0xc10af9 _start (/home/chris/llvmbase/llvm/build/Debug+Asserts/bin/llc+0xc10af9)
Stack dump:
0. Program arguments: /home/chris/llvmbase/llvm/build/Debug+Asserts/bin/llc -march=sparc -mcpu=leon2 /home/chris/llvmbase/llvm/lib/Target/Sparc/test.bc -o /home/chris/llvmbase/llvm/lib/Target/Sparc/test.s
1. Running pass 'Function Pass Manager' on module '/home/chris/llvmbase/llvm/lib/Target/Sparc/test.bc'.
2. Running pass 'ReplaceFMULS: Erratum Fix LBR32: replace FMULS instruction with a routine using conversions/double precision operations to replace FMULS' on function '@my_func'

Best Regards,
Chris Dewhurst.

It is very possible, but we won’t be able to really tell without seeing the code…

In general the statement: "MI.eraseFromParent();” invalidates the iterator that points to "MI". You need to increment it before removing the instruction.

See for instance ARMExpandPseudoInsts.cpp, ExpandMBB():

  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
  while (MBBI != E) {
    MachineBasicBlock::iterator NMBBI = std::next(MBBI);
    Modified |= ExpandMI(MBB, MBBI);
    MBBI = NMBBI;
  }

Or R600ExpandSpecialInstrsPass::runOnMachineFunction():

    MachineBasicBlock::iterator I = MBB.begin();
    while (I != MBB.end()) {
      MachineInstr &MI = *I;
      I = std::next(I);
      ...

Are you sure you need to actually do this as a post-processing pass after code generation? Why not setOperationAction(ISD::FMUL, MVT::i32, Promote); SparcISelLowering.cpp? I believe that'd avoid having it get generated in the first place (although I've not tested it).

Also: which erratum are you trying to work around? UT699's "FMULS precision loss after FDIVD/FSQRTD"? If so, I'd think that the workaround option of adding a "std %fNN, [%sp-8]" after fdivd/fsqrtd instructions may be better?

Hi,

I'm nearly there and, notwithstanding that it might be better to use setOperationAction (as indicated, James), this is representative of a class of problem that I'm trying to resolve in a few places, so I'll keep onto the original question, rather than re-framing it for a different problem.

The initial problem I posted for was with the iterator, which I needed to move onwards before removing the initial instruction. That is now OK and I have this working.

I belive my problem is now with registers. The code below runs well, but when it comes to outputting instructions it fails again. I believe this is a problem with using a virtual rather than a physical register, but I'm really not sure how or where to resolve this. Any help appreciated.

The bug in the instruction printer is:
static const char* llvm::SparcInstPrinter::getRegisterName(unsigned int): Assertion `RegNo && RegNo < 153 && "Invalid register number!"' failed.

RegNo = 0x8000000, which indicates a virtual register if I understand correctly.

The code I'm using to generate the new MI is below. This works fine, except that it produces instructions that later fail as indicated above:

bool MyPass::runOnMachineFunction(MachineFunction& MF)
{
  Subtarget = &MF.getSubtarget<SparcSubtarget>();
  const TargetInstrInfo& TII = *Subtarget->getInstrInfo();
  const TargetRegisterInfo* TRI = Subtarget->getRegisterInfo();
  const TargetRegisterClass* DoubleRC = TRI->getRegClass(SP::DFPRegsRegClassID);

  bool Modified = false;
  for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI)
  {
    MachineBasicBlock &MBB = *MFI;
    for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++ MBBI)
    {
      MachineInstr &MI = *MBBI;

      //MI.print(errs());
      unsigned Opcode = MI.getOpcode();
      if (Opcode == SP::FMULS)
      {
        MachineRegisterInfo& MRI = MF.getRegInfo();
        unsigned int f0 = MRI.createVirtualRegister(DoubleRC);
        MachineBasicBlock::iterator NMBBI = std::next(MBBI);
        MachineOperand& MOx = MI.getOperand(0);
        DebugLoc DL = MBBI->getDebugLoc();
        BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD), f0).addReg(MOx.getReg());
        // And so on for the other new instructions.
        MI.eraseFromParent();
        MBBI = NMBBI;
        Modified = true;
      }
    }
  }

  return Modified;
}