Implement a MachineFunctionPass to fix the mul instruction
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 19 Sep 2006 15:49:25 +0000 (15:49 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 19 Sep 2006 15:49:25 +0000 (15:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30485 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARM.h
lib/Target/ARM/ARMMul.cpp [new file with mode: 0644]
lib/Target/ARM/ARMTargetMachine.cpp
lib/Target/ARM/ARMTargetMachine.h
test/CodeGen/ARM/mul.ll [new file with mode: 0644]

index ca84634bed48a5bd33175da48f03c4eb9761b62f..49ed64dca518bcdbdfedbe91a15e041ba6355068 100644 (file)
@@ -77,6 +77,7 @@ namespace llvm {
 
   FunctionPass *createARMISelDag(TargetMachine &TM);
   FunctionPass *createARMCodePrinterPass(std::ostream &OS, TargetMachine &TM);
+  FunctionPass *createARMFixMulPass();
 } // end namespace llvm;
 
 // Defines symbolic names for ARM registers.  This defines a mapping from
diff --git a/lib/Target/ARM/ARMMul.cpp b/lib/Target/ARM/ARMMul.cpp
new file mode 100644 (file)
index 0000000..b984e7d
--- /dev/null
@@ -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;
+}
index ccf0fb7ed6758409f81980be360ac2bdd1c1e100..7506ea8c29ab3daf6ca1e0c9330d00bb1173554e 100644 (file)
@@ -54,10 +54,15 @@ bool ARMTargetMachine::addInstSelector(FunctionPassManager &PM, bool Fast) {
   PM.add(createARMISelDag(*this));
   return false;
 }
+
+bool ARMTargetMachine::addPostRegAlloc(FunctionPassManager &PM, bool Fast) {
+  PM.add(createARMFixMulPass());
+  return true;
+}
+
 bool ARMTargetMachine::addAssemblyEmitter(FunctionPassManager &PM, bool Fast, 
                                           std::ostream &Out) {
   // Output assembly language.
   PM.add(createARMCodePrinterPass(Out, *this));
   return false;
 }
-
index b453f0b64785b3c04ba611626419e3fedd68e0d5..b9a3d9809d2eed1dc995816b23f14c73aa7c92d5 100644 (file)
@@ -46,6 +46,7 @@ public:
 
   // Pass Pipeline Configuration
   virtual bool addInstSelector(FunctionPassManager &PM, bool Fast);
+  virtual bool addPostRegAlloc(FunctionPassManager &PM, bool Fast);
   virtual bool addAssemblyEmitter(FunctionPassManager &PM, bool Fast, 
                                   std::ostream &Out);
 };
diff --git a/test/CodeGen/ARM/mul.ll b/test/CodeGen/ARM/mul.ll
new file mode 100644 (file)
index 0000000..77f94f0
--- /dev/null
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -march=arm &&
+; RUN: llvm-as < %s | llc -march=arm | grep "mul r0, r12, r0"  | wc -l | grep 1 &&
+; RUN: llvm-as < %s | llc -march=arm | grep "mul r0, r1, r0"  | wc -l | grep 1
+
+int %mul1(int %u) {
+entry:
+       %tmp = mul int %u, %u;
+       ret int %tmp
+}
+
+int %mul2(int %u, int %v) {
+entry:
+       %tmp = mul int %u, %v;
+       ret int %tmp
+}