implement smull and umull
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 16 Oct 2006 16:33:29 +0000 (16:33 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 16 Oct 2006 16:33:29 +0000 (16:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30975 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMMul.cpp
lib/Target/ARM/README.txt
test/CodeGen/ARM/long.ll

index 17e0eecf971e430ab912fe6b4b5b97df2f6aa24e..6582a5b264258b98d1dffd009b30324d3546a83e 100644 (file)
@@ -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)]>;
index 185fb96783d7dbf06d120d8514b3bbd70d727e6c..474039db2774bee96d3012868e332f9bc5d2d5af 100644 (file)
@@ -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);
           }
         }
       }
index 06a8cceda547275ef4650d027219a9a24bc2ab06..768a2e6f3e4537374ff51d17740ca31dc342b1fc 100644 (file)
@@ -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.
+
+----------------------------------------------------------
index c01a4cb6130afa5cf28e1b6855e96f246be5f046..834f06871014feef0cda1db74a0318aac6f4cb4c 100644 (file)
@@ -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
+}