summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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