aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2006-10-16 16:33:29 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2006-10-16 16:33:29 +0000
commitbec2e38a9156aa35a200914a700de1e8d0810d80 (patch)
treea79aa753d1de31bddd2481898fa5bae508c1ed38
parentd9b8e40ab3b51fa49f0c35cccb2bd795a786162b (diff)
implement smull and umull
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30975 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td10
-rw-r--r--lib/Target/ARM/ARMMul.cpp14
-rw-r--r--lib/Target/ARM/README.txt5
-rw-r--r--test/CodeGen/ARM/long.ll20
4 files changed, 43 insertions, 6 deletions
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 17e0eecf97..6582a5b264 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -174,6 +174,16 @@ def MUL : InstARM<(ops IntRegs:$dst, IntRegs:$a, IntRegs:$b),
"mul $dst, $a, $b",
[(set IntRegs:$dst, (mul IntRegs:$a, IntRegs:$b))]>;
+let Defs = [R0] in {
+ def SMULL : InstARM<(ops IntRegs:$dst, IntRegs:$a, IntRegs:$b),
+ "smull r12, $dst, $a, $b",
+ [(set IntRegs:$dst, (mulhs IntRegs:$a, IntRegs:$b))]>;
+
+ def UMULL : InstARM<(ops IntRegs:$dst, IntRegs:$a, IntRegs:$b),
+ "umull r12, $dst, $a, $b",
+ [(set IntRegs:$dst, (mulhu IntRegs:$a, IntRegs:$b))]>;
+}
+
def bcond : InstARM<(ops brtarget:$dst, CCOp:$cc),
"b$cc $dst",
[(armbr bb:$dst, imm:$cc)]>;
diff --git a/lib/Target/ARM/ARMMul.cpp b/lib/Target/ARM/ARMMul.cpp
index 185fb96783..474039db27 100644
--- a/lib/Target/ARM/ARMMul.cpp
+++ b/lib/Target/ARM/ARMMul.cpp
@@ -8,7 +8,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Modify the ARM multiplication instructions so that Rd and Rm are distinct
+// Modify the ARM multiplication instructions so that Rd{Hi,Lo} and Rm are distinct
//
//===----------------------------------------------------------------------===//
@@ -39,7 +39,10 @@ bool FixMul::runOnMachineFunction(MachineFunction &MF) {
I != E; ++I) {
MachineInstr *MI = I;
- if (MI->getOpcode() == ARM::MUL) {
+ int Op = MI->getOpcode();
+ if (Op == ARM::MUL ||
+ Op == ARM::SMULL ||
+ Op == ARM::UMULL) {
MachineOperand &RdOp = MI->getOperand(0);
MachineOperand &RmOp = MI->getOperand(1);
MachineOperand &RsOp = MI->getOperand(2);
@@ -48,7 +51,7 @@ bool FixMul::runOnMachineFunction(MachineFunction &MF) {
unsigned Rm = RmOp.getReg();
unsigned Rs = RsOp.getReg();
- if(Rd == Rm) {
+ if (Rd == Rm) {
Changed = true;
if (Rd != Rs) {
//Rd and Rm must be distinct, but Rd can be equal to Rs.
@@ -56,9 +59,10 @@ bool FixMul::runOnMachineFunction(MachineFunction &MF) {
RmOp.setReg(Rs);
RsOp.setReg(Rm);
} else {
- BuildMI(MBB, I, ARM::MOV, 3, ARM::R12).addReg(Rm).addImm(0)
+ unsigned scratch = Op == ARM::MUL ? ARM::R12 : ARM::R0;
+ BuildMI(MBB, I, ARM::MOV, 3, scratch).addReg(Rm).addImm(0)
.addImm(ARMShift::LSL);
- RmOp.setReg(ARM::R12);
+ RmOp.setReg(scratch);
}
}
}
diff --git a/lib/Target/ARM/README.txt b/lib/Target/ARM/README.txt
index 06a8cceda5..768a2e6f3e 100644
--- a/lib/Target/ARM/README.txt
+++ b/lib/Target/ARM/README.txt
@@ -46,3 +46,8 @@ declare void %g(int, int, int, int, int)
Only needs 8 bytes of stack space. We currently allocate 16.
----------------------------------------------------------
+
+32 x 32 -> 64 multiplications currently uses two instructions. We
+should try to declare smull and umull as returning two values.
+
+----------------------------------------------------------
diff --git a/test/CodeGen/ARM/long.ll b/test/CodeGen/ARM/long.ll
index c01a4cb613..834f068710 100644
--- a/test/CodeGen/ARM/long.ll
+++ b/test/CodeGen/ARM/long.ll
@@ -7,7 +7,9 @@
; RUN: llvm-as < %s | llc -march=arm | grep "adds" | wc -l | grep 1 &&
; RUN: llvm-as < %s | llc -march=arm | grep "adcs" | wc -l | grep 1 &&
; RUN: llvm-as < %s | llc -march=arm | grep "subs" | wc -l | grep 1 &&
-; RUN: llvm-as < %s | llc -march=arm | grep "sbcs" | wc -l | grep 1
+; RUN: llvm-as < %s | llc -march=arm | grep "sbcs" | wc -l | grep 1 &&
+; RUN: llvm-as < %s | llc -march=arm | grep "smull" | wc -l | grep 1 &&
+; RUN: llvm-as < %s | llc -march=arm | grep "umull" | wc -l | grep 1
long %f1() {
entry:
@@ -52,3 +54,19 @@ entry:
%tmp = sub long %a, %b
ret long %tmp
}
+
+long %f(int %a, int %b) {
+entry:
+ %tmp = cast int %a to long
+ %tmp1 = cast int %b to long
+ %tmp2 = mul long %tmp1, %tmp
+ ret long %tmp2
+}
+
+ulong %g(uint %a, uint %b) {
+entry:
+ %tmp = cast uint %a to ulong
+ %tmp1 = cast uint %b to ulong
+ %tmp2 = mul ulong %tmp1, %tmp
+ ret ulong %tmp2
+}