[llvm-commits] [llvm] r164114 - in /llvm/trunk: lib/Target/ARM/ARMBaseInstrInfo.cpp test/CodeGen/ARM/domain-conv-vmovs.ll

James Molloy james.molloy at arm.com
Tue Sep 18 01:31:15 PDT 2012


Author: jamesm
Date: Tue Sep 18 03:31:15 2012
New Revision: 164114

URL: http://llvm.org/viewvc/llvm-project?rev=164114&view=rev
Log:
More domain conversion; convert VFP VMOVS to NEON instructions in more cases - when we may clobber the other S-lane by converting an S to a D instruction, make an effort to work out if the S lane is clobberable or not.


Modified:
    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
    llvm/trunk/test/CodeGen/ARM/domain-conv-vmovs.ll

Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=164114&r1=164113&r2=164114&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Tue Sep 18 03:31:15 2012
@@ -3425,6 +3425,48 @@
   return DReg;
 }
 
+/// getImplicitSPRUseForDPRUse - Given a use of a DPR register and lane, 
+/// set ImplicitSReg to a register number that must be marked as implicit-use or
+/// zero if no register needs to be defined as implicit-use.
+///
+/// If the function cannot determine if an SPR should be marked implicit use or
+/// not, it returns false.
+///
+/// This function handles cases where an instruction is being modified from taking
+/// an SPR to a DPR[Lane]. A use of the DPR is being added, which may conflict 
+/// with an earlier def of an SPR corresponding to DPR[Lane^1] (i.e. the other
+/// lane of the DPR).
+///
+/// If the other SPR is defined, an implicit-use of it should be added. Else,
+/// (including the case where the DPR itself is defined), it should not.
+/// 
+static bool getImplicitSPRUseForDPRUse(const TargetRegisterInfo *TRI,
+                                       MachineInstr *MI,
+                                       unsigned DReg, unsigned Lane,
+                                       unsigned &ImplicitSReg) {
+  // If the DPR is defined or used already, the other SPR lane will be chained
+  // correctly, so there is nothing to be done.
+  if (MI->definesRegister(DReg, TRI) || MI->readsRegister(DReg, TRI)) {
+    ImplicitSReg = 0;
+    return true;
+  }
+
+  // Otherwise we need to go searching to see if the SPR is set explicitly.
+  ImplicitSReg = TRI->getSubReg(DReg,
+                                (Lane & 1) ? ARM::ssub_0 : ARM::ssub_1);
+  MachineBasicBlock::LivenessQueryResult LQR =
+    MI->getParent()->computeRegisterLiveness(TRI, ImplicitSReg, MI);
+
+  if (LQR == MachineBasicBlock::LQR_Live)
+    return true;
+  else if (LQR == MachineBasicBlock::LQR_Unknown)
+    return false;
+
+  // If the register is known not to be live, there is no need to add an
+  // implicit-use.
+  ImplicitSReg = 0;
+  return true;
+}
 
 void
 ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
@@ -3482,7 +3524,7 @@
       // was dead before here.
       MIB.addReg(SrcReg, RegState::Implicit);
       break;
-    case ARM::VMOVSR:
+    case ARM::VMOVSR: {
       if (Domain != ExeNEON)
         break;
       assert(!isPredicated(MI) && "Cannot predicate a VSETLN");
@@ -3493,12 +3535,9 @@
 
       DReg = getCorrespondingDRegAndLane(TRI, DstReg, Lane);
 
-      // If we insert both a novel <def> and an <undef> on the DReg, we break
-      // any existing dependency chain on the unused lane. Either already being
-      // present means this instruction is in that chain anyway so we can make
-      // the transformation.
-      if (!MI->definesRegister(DReg, TRI) && !MI->readsRegister(DReg, TRI))
-          break;
+      unsigned ImplicitSReg;
+      if (!getImplicitSPRUseForDPRUse(TRI, MI, DReg, Lane, ImplicitSReg))
+        break;
 
       for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
         MI->RemoveOperand(i-1);
@@ -3515,7 +3554,10 @@
       // The narrower destination must be marked as set to keep previous chains
       // in place.
       MIB.addReg(DstReg, RegState::Define | RegState::Implicit);
+      if (ImplicitSReg != 0)
+        MIB.addReg(ImplicitSReg, RegState::Implicit);
       break;
+    }
     case ARM::VMOVS: {
       if (Domain != ExeNEON)
         break;
@@ -3528,12 +3570,9 @@
       DDst = getCorrespondingDRegAndLane(TRI, DstReg, DstLane);
       DSrc = getCorrespondingDRegAndLane(TRI, SrcReg, SrcLane);
 
-      // If we insert both a novel <def> and an <undef> on the DReg, we break
-      // any existing dependency chain on the unused lane. Either already being
-      // present means this instruction is in that chain anyway so we can make
-      // the transformation.
-      if (!MI->definesRegister(DDst, TRI) && !MI->readsRegister(DDst, TRI))
-          break;
+      unsigned ImplicitSReg;
+      if (!getImplicitSPRUseForDPRUse(TRI, MI, DSrc, SrcLane, ImplicitSReg))
+        break;
 
       for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
         MI->RemoveOperand(i-1);
@@ -3551,6 +3590,8 @@
         // more, so add them in manually.
         MIB.addReg(DstReg, RegState::Implicit | RegState::Define);
         MIB.addReg(SrcReg, RegState::Implicit);
+        if (ImplicitSReg != 0)
+          MIB.addReg(ImplicitSReg, RegState::Implicit);
         break;
       }
 
@@ -3609,6 +3650,8 @@
       // As before, the original destination is no longer represented, add it
       // implicitly.
       MIB.addReg(DstReg, RegState::Define | RegState::Implicit);
+      if (ImplicitSReg != 0)
+        MIB.addReg(ImplicitSReg, RegState::Implicit);
       break;
     }
   }

Modified: llvm/trunk/test/CodeGen/ARM/domain-conv-vmovs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/domain-conv-vmovs.ll?rev=164114&r1=164113&r2=164114&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/domain-conv-vmovs.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/domain-conv-vmovs.ll Tue Sep 18 03:31:15 2012
@@ -79,6 +79,22 @@
   ; internal fault).
   call void @bar()
 ; CHECL: bl bar
-; CHECK: vmov.f32 {{s[0-9]+}}, {{s[0-9]+}}
+; CHECK: vext.32 
+; CHECK: vext.32 
   ret float %val
-}
\ No newline at end of file
+}
+
+define i32 @test_vmovs_no_sreg(i32 %in) {
+; CHECK: test_vmovs_no_sreg:
+
+  ; Check that the movement to and from GPRs takes place in the NEON domain.
+; CHECK: vmov.32 d
+  %x = bitcast i32 %in to float
+
+  %res = fadd float %x, %x
+
+; CHECK: vmov.32 r{{[0-9]+}}, d
+  %resi = bitcast float %res to i32
+
+  ret i32 %resi
+}





More information about the llvm-commits mailing list