Skip to content

Commit

Permalink
Summary
Browse files Browse the repository at this point in the history
PPC backend eliminates compare instructions by using record-form instructions in PPCInstrInfo::optimizeCompareInstr, which is called from peephole optimization pass.
This patch improves this optimization to eliminate more compare instructions in two types of common case.


- comparison against a constant 1 or -1

The record-form instructions set CR bit based on signed comparison against 0. So, the current implementation does not exploit the record-form instruction for comparison against a non-zero constant.
This patch enables record-form optimization for constant of 1 or -1 if possible; it changes the condition "greater than -1" into "greater than or equal to 0" and "less than 1" into "less than or equal to 0".
With this patch, compare can be eliminated in the following code sequence, as an example.

uint64_t a, b;
if ((a | b) & 0x8000000000000000ull) { ... }
else { ... }


- andi for 32-bit comparison on PPC64

Since record-form instructions execute 64-bit signed comparison and so we have limitation in eliminating 32-bit comparison, i.e. with cmplwi, using the record-form. The original implementation already has such checks but andi. is not recognized as an instruction which executes implicit zero extension and hence safe to convert into record-form if used for equality check.

%1 = and i32 %a, 10
%2 = icmp ne i32 %1, 0
br i1 %2, label %foo, label %bar

In this simple example, LLVM generates andi. + cmplwi + beq on PPC64.
This patch make it possible to eliminate the cmplwi for this case.
I added andi. for optimization targets if it is safe to do so.

Differential Revision: https://reviews.llvm.org/D30081

llvm-svn: 303500
  • Loading branch information
inouehrs committed May 21, 2017
1 parent 7533ac1 commit 37e63b1
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 6 deletions.
50 changes: 44 additions & 6 deletions llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1533,6 +1533,8 @@ bool PPCInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
case PPC::FCMPUD:
SrcReg = MI.getOperand(1).getReg();
SrcReg2 = MI.getOperand(2).getReg();
Value = 0;
Mask = 0;
return true;
}
}
Expand Down Expand Up @@ -1591,9 +1593,12 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,

// We can perform this optimization, equality only, if MI is
// zero-extending.
// FIXME: Other possible target instructions include ANDISo and
// RLWINM aliases, such as ROTRWI, EXTLWI, SLWI and SRWI.
if (MIOpC == PPC::CNTLZW || MIOpC == PPC::CNTLZWo ||
MIOpC == PPC::SLW || MIOpC == PPC::SLWo ||
MIOpC == PPC::SRW || MIOpC == PPC::SRWo ||
MIOpC == PPC::ANDIo ||
isZeroExtendingRotate) {
noSub = true;
equalityOnly = true;
Expand Down Expand Up @@ -1641,6 +1646,9 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
break;
}

SmallVector<std::pair<MachineOperand*, PPC::Predicate>, 4> PredsToUpdate;
SmallVector<std::pair<MachineOperand*, unsigned>, 4> SubRegsToUpdate;

// There are two possible candidates which can be changed to set CR[01].
// One is MI, the other is a SUB instruction.
// For CMPrr(r1,r2), we are looking for SUB(r1,r2) or SUB(r2,r1).
Expand All @@ -1652,9 +1660,37 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
// same BB as the comparison. This is to allow the check below to avoid calls
// (and other explicit clobbers); instead we should really check for these
// more explicitly (in at least a few predecessors).
else if (MI->getParent() != CmpInstr.getParent() || Value != 0) {
// PPC does not have a record-form SUBri.
else if (MI->getParent() != CmpInstr.getParent())
return false;
else if (Value != 0) {
// The record-form instructions set CR bit based on signed comparison against 0.
// We try to convert a compare against 1 or -1 into a compare against 0.
bool Success = false;
if (!equalityOnly && MRI->hasOneUse(CRReg)) {
MachineInstr *UseMI = &*MRI->use_instr_begin(CRReg);
if (UseMI->getOpcode() == PPC::BCC) {
PPC::Predicate Pred = (PPC::Predicate)UseMI->getOperand(0).getImm();
int16_t Immed = (int16_t)Value;

if (Immed == -1 && Pred == PPC::PRED_GT) {
// We convert "greater than -1" into "greater than or equal to 0",
// since we are assuming signed comparison by !equalityOnly
PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)),
PPC::PRED_GE));
Success = true;
}
else if (Immed == 1 && Pred == PPC::PRED_LT) {
// We convert "less than 1" into "less than or equal to 0".
PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)),
PPC::PRED_LE));
Success = true;
}
}
}

// PPC does not have a record-form SUBri.
if (!Success)
return false;
}

// Search for Sub.
Expand Down Expand Up @@ -1720,15 +1756,14 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
if (NewOpC == -1)
return false;

SmallVector<std::pair<MachineOperand*, PPC::Predicate>, 4> PredsToUpdate;
SmallVector<std::pair<MachineOperand*, unsigned>, 4> SubRegsToUpdate;

// If we have SUB(r1, r2) and CMP(r2, r1), the condition code based on CMP
// needs to be updated to be based on SUB. Push the condition code
// operands to OperandsToUpdate. If it is safe to remove CmpInstr, the
// condition code of these operands will be modified.
// Here, Value == 0 means we haven't converted comparison against 1 or -1 to
// comparison against 0, which may modify predicate.
bool ShouldSwap = false;
if (Sub) {
if (Sub && Value == 0) {
ShouldSwap = SrcReg2 != 0 && Sub->getOperand(1).getReg() == SrcReg2 &&
Sub->getOperand(2).getReg() == SrcReg;

Expand Down Expand Up @@ -1765,6 +1800,9 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
} else // We need to abort on a user we don't understand.
return false;
}
assert(!(Value != 0 && ShouldSwap) &&
"Non-zero immediate support and ShouldSwap"
"may conflict in updating predicate");

// Create a new virtual register to hold the value of the CR set by the
// record-form instruction. If the instruction was not previously in
Expand Down
33 changes: 33 additions & 0 deletions llvm/test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
; RUN: llc -verify-machineinstrs -print-before=peephole-opt -print-after=peephole-opt -mtriple=powerpc64-unknown-linux-gnu -o /dev/null 2>&1 < %s | FileCheck %s

; CHECK-LABEL: fn1
define signext i32 @fn1(i32 %baz) {
%1 = mul nsw i32 %baz, 208
%2 = zext i32 %1 to i64
Expand All @@ -21,3 +22,35 @@ foo:
bar:
ret i32 0
}

; CHECK-LABEL: fn2
define signext i32 @fn2(i64 %a, i64 %b) {
; CHECK: OR8o {{[^, ]+}}, {{[^, ]+}}, %CR0<imp-def>;
; CHECK: [[CREG:[^, ]+]]<def> = COPY %CR0
; CHECK: BCC 12, [[CREG]]<kill>
%1 = or i64 %b, %a
%2 = icmp sgt i64 %1, -1
br i1 %2, label %foo, label %bar

foo:
ret i32 1

bar:
ret i32 0
}

; CHECK-LABEL: fn3
define signext i32 @fn3(i32 %a) {
; CHECK: ANDIo {{[^, ]+}}, 10, %CR0<imp-def>;
; CHECK: [[CREG:[^, ]+]]<def> = COPY %CR0
; CHECK: BCC 76, [[CREG]]<kill>
%1 = and i32 %a, 10
%2 = icmp ne i32 %1, 0
br i1 %2, label %foo, label %bar

foo:
ret i32 1

bar:
ret i32 0
}

0 comments on commit 37e63b1

Please sign in to comment.