case PPC::FCMPUD:
SrcReg = MI.getOperand(1).getReg();
SrcReg2 = MI.getOperand(2).getReg();
+ Value = 0;
+ Mask = 0;
return true;
}
}
// 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;
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).
// 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.
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;
} 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
; 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
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
+}