summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@linaro.org>2019-07-22 08:44:36 +0000
committerOliver Stannard <oliver.stannard@linaro.org>2019-07-22 08:44:36 +0000
commit6771a89fa01ffb1ea8702d7b07e259750ae62f1c (patch)
tree7ceb6534c6439741779f2c018a188d97bd9067eb
parent6522a7df544efe391519ffd35651a80d6a2186ae (diff)
downloadbcm5719-llvm-6771a89fa01ffb1ea8702d7b07e259750ae62f1c.tar.gz
bcm5719-llvm-6771a89fa01ffb1ea8702d7b07e259750ae62f1c.zip
[IPRA][ARM] Make use of the "returned" parameter attribute
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 llvm-svn: 366669
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp2
-rw-r--r--llvm/lib/Target/ARM/ARMFrameLowering.cpp6
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp6
-rw-r--r--llvm/lib/Target/ARM/ARMMachineFunctionInfo.h7
-rw-r--r--llvm/test/CodeGen/ARM/ipra-r0-returned.ll18
5 files changed, 39 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 72c76878f2c..bf07b600004 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -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);
diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
index bedb779bcba..7ae0c6ab3cf 100644
--- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
@@ -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(
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 18bb9bf3ecc..ee619353897 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -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
diff --git a/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h b/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h
index 90d794cd27b..e80c2c64123 100644
--- a/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h
+++ b/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h
@@ -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/llvm/test/CodeGen/ARM/ipra-r0-returned.ll b/llvm/test/CodeGen/ARM/ipra-r0-returned.ll
new file mode 100644
index 00000000000..cd3069c0c58
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/ipra-r0-returned.ll
@@ -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
+}
OpenPOWER on IntegriCloud