Skip to content

Commit

Permalink
[IPRA][ARM] Make use of the "returned" parameter attribute
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ostannard committed Jul 22, 2019
1 parent 6522a7d commit 6771a89
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 0 deletions.
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/ARM/ARMFrameLowering.cpp
Expand Up @@ -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(
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/ARM/ARMMachineFunctionInfo.h
Expand Up @@ -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;

Expand Down Expand Up @@ -247,6 +251,9 @@ class ARMFunctionInfo : public MachineFunctionInfo {
}

DenseMap<unsigned, unsigned> EHPrologueRemappedRegs;

void setPreservesR0() { PreservesR0 = true; }
bool getPreservesR0() const { return PreservesR0; }
};

} // end namespace llvm
Expand Down
18 changes: 18 additions & 0 deletions 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
}

0 comments on commit 6771a89

Please sign in to comment.