Implement a MachineFunctionPass to fix the mul instruction


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30485 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMMul.cpp b/lib/Target/ARM/ARMMul.cpp
new file mode 100644
index 0000000..b984e7d
--- /dev/null
+++ b/lib/Target/ARM/ARMMul.cpp
@@ -0,0 +1,66 @@
+//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ARM.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace llvm;
+
+namespace {
+  class VISIBILITY_HIDDEN FixMul : public MachineFunctionPass {
+    virtual bool runOnMachineFunction(MachineFunction &MF);
+  };
+}
+
+FunctionPass *llvm::createARMFixMulPass() { return new FixMul(); }
+
+bool FixMul::runOnMachineFunction(MachineFunction &MF) {
+  bool Changed = false;
+
+  for (MachineFunction::iterator BB = MF.begin(), E = MF.end();
+       BB != E; ++BB) {
+    MachineBasicBlock &MBB = *BB;
+
+    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
+         I != E; ++I) {
+      MachineInstr *MI = I;
+
+      if (MI->getOpcode() == ARM::MUL) {
+	MachineOperand &RdOp = MI->getOperand(0);
+	MachineOperand &RmOp = MI->getOperand(1);
+	MachineOperand &RsOp = MI->getOperand(2);
+
+	unsigned Rd = RdOp.getReg();
+	unsigned Rm = RmOp.getReg();
+	unsigned Rs = RsOp.getReg();
+
+	if(Rd == Rm) {
+	  Changed = true;
+	  if (Rd != Rs) {
+	    RmOp.setReg(Rs);
+	    RsOp.setReg(Rm);
+	  } else {
+	    BuildMI(MBB, I, ARM::MOV, 3, ARM::R12).addReg(Rm).addImm(0)
+	      .addImm(ARMShift::LSL);
+	    RmOp.setReg(ARM::R12);
+	  }
+	}
+      }
+    }
+  }
+
+  return Changed;
+}