diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index ca84634bed4..49ed64dca51 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -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 index 00000000000..b984e7dc5c5 --- /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; +} diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index ccf0fb7ed67..7506ea8c29a 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -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; } - diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h index b453f0b6478..b9a3d9809d2 100644 --- a/lib/Target/ARM/ARMTargetMachine.h +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -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 index 00000000000..77f94f087f3 --- /dev/null +++ b/test/CodeGen/ARM/mul.ll @@ -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 +}