[llvm] r319087 - [PowerPC] Remove redundant TOC saves
Zaara Syeda via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 27 12:26:36 PST 2017
Author: syzaara
Date: Mon Nov 27 12:26:36 2017
New Revision: 319087
URL: http://llvm.org/viewvc/llvm-project?rev=319087&view=rev
Log:
[PowerPC] Remove redundant TOC saves
This patch adds a peep hole optimization to remove any redundant toc save
instructions added as part of the call sequence for indirect calls. It removes
any toc saves within a function that are dominated by another toc save.
Differential Revision: https://reviews.llvm.org/D39736
Added:
llvm/trunk/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll
Modified:
llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp
llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h
llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp
Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp?rev=319087&r1=319086&r2=319087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp Mon Nov 27 12:26:36 2017
@@ -2266,6 +2266,20 @@ static bool isZeroExtendingOp(const Mach
return false;
}
+// This function returns true if the input MachineInstr is a TOC save
+// instruction.
+bool PPCInstrInfo::isTOCSaveMI(const MachineInstr &MI) const {
+ if (!MI.getOperand(1).isImm() || !MI.getOperand(2).isReg())
+ return false;
+ unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset();
+ unsigned StackOffset = MI.getOperand(1).getImm();
+ unsigned StackReg = MI.getOperand(2).getReg();
+ if (StackReg == PPC::X1 && StackOffset == TOCSaveOffset)
+ return true;
+
+ return false;
+}
+
// We limit the max depth to track incoming values of PHIs or binary ops
// (e.g. AND) to avoid exsessive cost.
const unsigned MAX_DEPTH = 1;
Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h?rev=319087&r1=319086&r2=319087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h Mon Nov 27 12:26:36 2017
@@ -297,6 +297,8 @@ public:
const TargetRegisterClass *updatedRC(const TargetRegisterClass *RC) const;
static int getRecordFormOpcode(unsigned Opcode);
+ bool isTOCSaveMI(const MachineInstr &MI) const;
+
bool isSignOrZeroExtended(const MachineInstr &MI, bool SignExt,
const unsigned PhiDepth) const;
Modified: llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp?rev=319087&r1=319086&r2=319087&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCMIPeephole.cpp Mon Nov 27 12:26:36 2017
@@ -29,13 +29,15 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
-#include "llvm/ADT/Statistic.h"
#include "MCTargetDesc/PPCPredicates.h"
using namespace llvm;
#define DEBUG_TYPE "ppc-mi-peepholes"
+STATISTIC(RemoveTOCSave, "Number of TOC saves removed");
+STATISTIC(MultiTOCSaves,
+ "Number of functions with multiple TOC saves that must be kept");
STATISTIC(NumEliminatedSExt, "Number of eliminated sign-extensions");
STATISTIC(NumEliminatedZExt, "Number of eliminated zero-extensions");
STATISTIC(NumOptADDLIs, "Number of optimized ADD instruction fed by LI");
@@ -78,7 +80,9 @@ private:
// Perform peepholes.
bool eliminateRedundantCompare(void);
-
+ bool eliminateRedundantTOCSaves(std::map<MachineInstr *, bool> &TOCSaves);
+ void UpdateTOCSaves(std::map<MachineInstr *, bool> &TOCSaves,
+ MachineInstr *MI);
// Find the "true" register represented by SrcReg (following chains
// of copies and subreg_to_reg operations).
unsigned lookThruCopyLike(unsigned SrcReg);
@@ -176,10 +180,37 @@ getKnownLeadingZeroCount(MachineInstr *M
return 0;
}
+// This function maintains a map for the pairs <TOC Save Instr, Keep>
+// Each time a new TOC save is encountered, it checks if any of the exisiting
+// ones are dominated by the new one. If so, it marks the exisiting one as
+// redundant by setting it's entry in the map as false. It then adds the new
+// instruction to the map with either true or false depending on if any
+// exisiting instructions dominated the new one.
+void PPCMIPeephole::UpdateTOCSaves(
+ std::map<MachineInstr *, bool> &TOCSaves, MachineInstr *MI) {
+ assert(TII->isTOCSaveMI(*MI) && "Expecting a TOC save instruction here");
+ bool Keep = true;
+ for (auto It = TOCSaves.begin(); It != TOCSaves.end(); It++ ) {
+ MachineInstr *CurrInst = It->first;
+ // If new instruction dominates an exisiting one, mark exisiting one as
+ // redundant.
+ if (It->second && MDT->dominates(MI, CurrInst))
+ It->second = false;
+ // Check if the new instruction is redundant.
+ if (MDT->dominates(CurrInst, MI)) {
+ Keep = false;
+ break;
+ }
+ }
+ // Add new instruction to map.
+ TOCSaves[MI] = Keep;
+}
+
// Perform peephole optimizations.
bool PPCMIPeephole::simplifyCode(void) {
bool Simplified = false;
MachineInstr* ToErase = nullptr;
+ std::map<MachineInstr *, bool> TOCSaves;
for (MachineBasicBlock &MBB : *MF) {
for (MachineInstr &MI : MBB) {
@@ -201,6 +232,18 @@ bool PPCMIPeephole::simplifyCode(void) {
default:
break;
+ case PPC::STD: {
+ MachineFrameInfo &MFI = MF->getFrameInfo();
+ if (MFI.hasVarSizedObjects() ||
+ !MF->getSubtarget<PPCSubtarget>().isELFv2ABI())
+ break;
+ // When encountering a TOC save instruction, call UpdateTOCSaves
+ // to add it to the TOCSaves map and mark any exisiting TOC saves
+ // it dominates as redundant.
+ if (TII->isTOCSaveMI(MI))
+ UpdateTOCSaves(TOCSaves, &MI);
+ break;
+ }
case PPC::XXPERMDI: {
// Perform simplifications of 2x64 vector swaps and splats.
// A swap is identified by an immediate value of 2, and a splat
@@ -683,6 +726,8 @@ bool PPCMIPeephole::simplifyCode(void) {
}
}
+ // Eliminate all the TOC save instructions which are redundant.
+ Simplified |= eliminateRedundantTOCSaves(TOCSaves);
// We try to eliminate redundant compare instruction.
Simplified |= eliminateRedundantCompare();
@@ -888,6 +933,30 @@ static bool eligibleForCompareEliminatio
return false;
}
+// This function will iterate over the input map containing a pair of TOC save
+// instruction and a flag. The flag will be set to false if the TOC save is proven
+// redundant. This function will erase from the basic block all the TOC saves
+// marked as redundant.
+bool PPCMIPeephole::eliminateRedundantTOCSaves(
+ std::map<MachineInstr *, bool> &TOCSaves) {
+ bool Simplified = false;
+ int NumKept = 0;
+ for (auto TOCSave : TOCSaves) {
+ if (!TOCSave.second) {
+ TOCSave.first->eraseFromParent();
+ RemoveTOCSave++;
+ Simplified = true;
+ } else {
+ NumKept++;
+ }
+ }
+
+ if (NumKept > 1)
+ MultiTOCSaves++;
+
+ return Simplified;
+}
+
// If multiple conditional branches are executed based on the (essentially)
// same comparison, we merge compare instructions into one and make multiple
// conditional branches on this comparison.
Added: llvm/trunk/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll?rev=319087&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll Mon Nov 27 12:26:36 2017
@@ -0,0 +1,123 @@
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
+define signext i32 @test1(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
+entry:
+; CHECK-LABEL: test1:
+; CHECK: std 2, 24(1)
+; CHECK-NOT: std 2, 24(1)
+ %call = tail call signext i32 %Func(i32 signext %i)
+ %call1 = tail call signext i32 %Func2(i32 signext %i)
+ %add2 = add nsw i32 %call1, %call
+ ret i32 %add2
+}
+
+define signext i32 @test2(i32 signext %i, i32 signext %j, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
+entry:
+; CHECK-LABEL: test2:
+; CHECK: std 2, 24(1)
+; CHECK-NOT: std 2, 24(1)
+ %call = tail call signext i32 %Func(i32 signext %i)
+ %tobool = icmp eq i32 %j, 0
+ br i1 %tobool, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ %call1 = tail call signext i32 %Func(i32 signext %i)
+ %add2 = add nsw i32 %call1, %call
+ %call3 = tail call signext i32 %Func2(i32 signext %i)
+ %add4 = add nsw i32 %add2, %call3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ %Sum.0 = phi i32 [ %add4, %if.then ], [ %call, %entry ]
+ %call5 = tail call signext i32 %Func(i32 signext %i)
+ %add6 = add nsw i32 %call5, %Sum.0
+ ret i32 %add6
+}
+
+; Check for multiple TOC saves with if then else where neither dominates the other.
+define signext i32 @test3(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
+; CHECK-LABEL: test3:
+; CHECK: std 2, 24(1)
+; CHECK: std 2, 24(1)
+; CHECK-NOT: std 2, 24(1)
+entry:
+ %tobool = icmp eq i32 %i, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ %call = tail call signext i32 %Func(i32 signext %i)
+ br label %if.end
+
+if.else: ; preds = %entry
+ %call1 = tail call signext i32 %Func2(i32 signext 0)
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %Sum.0 = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
+ %call3 = tail call signext i32 %Func(i32 signext %i)
+ %add4 = add nsw i32 %call3, %Sum.0
+ ret i32 %add4
+}
+
+define signext i32 @test4(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
+; CHECK-LABEL: test4:
+; CHECK: std 2, 24(1)
+; CHECK-NOT: std 2, 24(1)
+
+entry:
+ %call = tail call signext i32 %Func(i32 signext %i)
+ %tobool = icmp eq i32 %i, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ %call1 = tail call signext i32 %Func(i32 signext %i)
+ br label %if.end
+
+if.else: ; preds = %entry
+ %call3 = tail call signext i32 %Func2(i32 signext 0)
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %call1.pn = phi i32 [ %call1, %if.then ], [ %call3, %if.else ]
+ %Sum.0 = add nsw i32 %call1.pn, %call
+ ret i32 %Sum.0
+}
+
+; Check for multiple TOC saves with if then where neither is redundant.
+define signext i32 @test5(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture readnone %Func2) {
+entry:
+; CHECK-LABEL: test5:
+; CHECK: std 2, 24(1)
+; CHECK: std 2, 24(1)
+
+ %tobool = icmp eq i32 %i, 0
+ br i1 %tobool, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ %call = tail call signext i32 %Func(i32 signext %i)
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ %Sum.0 = phi i32 [ %call, %if.then ], [ 0, %entry ]
+ %call1 = tail call signext i32 %Func(i32 signext %i)
+ %add2 = add nsw i32 %call1, %Sum.0
+ ret i32 %add2
+}
+
+; Check for multiple TOC saves if there are dynamic allocations on the stack.
+define signext i32 @test6(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
+entry:
+; CHECK-LABEL: test6:
+; CHECK: std 2, 24(1)
+; CHECK: std 2, 24(1)
+
+ %conv = sext i32 %i to i64
+ %0 = alloca i8, i64 %conv, align 16
+ %1 = bitcast i8* %0 to i32*
+ %call = tail call signext i32 %Func(i32 signext %i)
+ call void @useAlloca(i32* nonnull %1, i32 signext %call)
+ %call1 = call signext i32 %Func2(i32 signext %i)
+ %add2 = add nsw i32 %call1, %call
+ ret i32 %add2
+}
+
+declare void @useAlloca(i32*, i32 signext)
More information about the llvm-commits
mailing list