]> granicus.if.org Git - llvm/commitdiff
[IPRA][ARM] Make use of the "returned" parameter attribute
authorOliver Stannard <oliver.stannard@linaro.org>
Mon, 22 Jul 2019 08:44:36 +0000 (08:44 +0000)
committerOliver Stannard <oliver.stannard@linaro.org>
Mon, 22 Jul 2019 08:44:36 +0000 (08:44 +0000)
ARM has code to recognise uses of the "returned" function parameter
attribute which guarantee that the value passed to the function in r0
will be returned in r0 unmodified. IPRA replaces the regmask on call
instructions, so needs to be told about this to avoid reverting the
optimisation.

Differential revision: https://reviews.llvm.org/D64986

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366669 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/Target/ARM/ARMFrameLowering.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMMachineFunctionInfo.h
test/CodeGen/ARM/ipra-r0-returned.ll [new file with mode: 0644]

index 72c76878f2c718cfe32e6a9482ce3d39da707117..bf07b60000400ae4216961ac3a51959c88754280 100644 (file)
@@ -9615,6 +9615,8 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
       Flags.setOrigAlign(OriginalAlignment);
       if (ArgCopyElisionCandidates.count(&Arg))
         Flags.setCopyElisionCandidate();
+      if (Arg.hasAttribute(Attribute::Returned))
+        Flags.setReturned();
 
       MVT RegisterVT = TLI->getRegisterTypeForCallingConv(
           *CurDAG->getContext(), F.getCallingConv(), VT);
index bedb779bcba09b3a7e185b52dc880d1b8247fd43..7ae0c6ab3cf8ed38856c2466c55052b2a68a5446 100644 (file)
@@ -2097,6 +2097,12 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
     AFI->setLRIsSpilledForFarJump(true);
   }
   AFI->setLRIsSpilled(SavedRegs.test(ARM::LR));
+
+  // If we have the "returned" parameter attribute which guarantees that we
+  // return the value which was passed in r0 unmodified (e.g. C++ 'structors),
+  // record that fact for IPRA.
+  if (AFI->getPreservesR0())
+    SavedRegs.set(ARM::R0);
 }
 
 MachineBasicBlock::iterator ARMFrameLowering::eliminateCallFramePseudoInstr(
index 18bb9bf3eccc640b3bd93031832c5bd297044e8b..ee619353897792a6b486bd177542b6696b68578f 100644 (file)
@@ -3898,6 +3898,12 @@ SDValue ARMTargetLowering::LowerFormalArguments(
         // Transform the arguments in physical registers into virtual ones.
         unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
         ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
+
+        // If this value is passed in r0 and has the returned attribute (e.g.
+        // C++ 'structors), record this fact for later use.
+        if (VA.getLocReg() == ARM::R0 && Ins[VA.getValNo()].Flags.isReturned()) {
+          AFI->setPreservesR0();
+        }
       }
 
       // If this is an 8 or 16-bit value, it is really passed promoted
index 90d794cd27b126c5040da1e34b2eb9cd6ea1521f..e80c2c6412321dcc38291ef6fc0f0d671149f4c0 100644 (file)
@@ -130,6 +130,10 @@ class ARMFunctionInfo : public MachineFunctionInfo {
   /// The amount the literal pool has been increasedby due to promoted globals.
   int PromotedGlobalsIncrease = 0;
 
+  /// True if r0 will be preserved by a call to this function (e.g. C++
+  /// con/destructors).
+  bool PreservesR0 = false;
+
 public:
   ARMFunctionInfo() = default;
 
@@ -247,6 +251,9 @@ public:
   }
 
   DenseMap<unsigned, unsigned> EHPrologueRemappedRegs;
+
+  void setPreservesR0() { PreservesR0 = true; }
+  bool getPreservesR0() const { return PreservesR0; }
 };
 
 } // end namespace llvm
diff --git a/test/CodeGen/ARM/ipra-r0-returned.ll b/test/CodeGen/ARM/ipra-r0-returned.ll
new file mode 100644 (file)
index 0000000..cd3069c
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: llc -mtriple armv7a--none-eabi -enable-ipra=false < %s | FileCheck %s
+; RUN: llc -mtriple armv7a--none-eabi -enable-ipra=true  < %s | FileCheck %s
+
+define i32 @returns_r0(i32 returned %a)  {
+entry:
+  call void asm sideeffect "", "~{r0}"()
+  ret i32 %a
+}
+
+define i32 @test(i32 %a) {
+; CHECK-LABEL: test:
+entry:
+; CHECK-NOT: r0
+; CHECK: bl      returns_r0
+; CHECK-NOT: r0
+  %b = call i32 @returns_r0(i32 %a)
+  ret i32 %a
+}