forked from OSchip/llvm-project
[ARM] CMOV->BFI combining: handle both senses of CMPZ
I completely misunderstood what ARMISD::CMPZ means. It's not "compare equal to zero", it's "compare, only setting the zero/Z flag". It can either be equal-to-zero or not-equal-to-zero, and we weren't checking what sense it was. If it's equal-to-zero, we can swap the operands around and pretend like it is not-equal-to-zero, which is both a bug fix and lets us handle more cases. llvm-svn: 252891
This commit is contained in:
parent
19a17c3a16
commit
8e99e97f2a
|
@ -10393,6 +10393,8 @@ SDValue ARMTargetLowering::PerformCMOVToBFICombine(SDNode *CMOV, SelectionDAG &D
|
|||
|
||||
SDValue Op0 = CMOV->getOperand(0);
|
||||
SDValue Op1 = CMOV->getOperand(1);
|
||||
auto CCNode = cast<ConstantSDNode>(CMOV->getOperand(2));
|
||||
auto CC = CCNode->getAPIntValue().getLimitedValue();
|
||||
SDValue CmpZ = CMOV->getOperand(4);
|
||||
|
||||
assert(CmpZ->getOpcode() == ARMISD::CMPZ);
|
||||
|
@ -10404,6 +10406,14 @@ SDValue ARMTargetLowering::PerformCMOVToBFICombine(SDNode *CMOV, SelectionDAG &D
|
|||
return SDValue();
|
||||
SDValue X = And->getOperand(0);
|
||||
|
||||
if (CC == ARMCC::EQ) {
|
||||
// We're performing an "equal to zero" compare. Swap the operands so we
|
||||
// canonicalize on a "not equal to zero" compare.
|
||||
std::swap(Op0, Op1);
|
||||
} else {
|
||||
assert(CC == ARMCC::NE && "How can a CMPZ node not be EQ or NE?");
|
||||
}
|
||||
|
||||
if (Op1->getOpcode() != ISD::OR)
|
||||
return SDValue();
|
||||
|
||||
|
|
|
@ -147,3 +147,14 @@ define i32 @f11(i32 %x, i32 %y) {
|
|||
|
||||
ret i32 %bsel
|
||||
}
|
||||
|
||||
define i32 @f12(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: f12:
|
||||
; CHECK: bfi r1, r0, #4, #1
|
||||
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
||||
%and = and i32 %x, 4
|
||||
%or = or i32 %y2, 16
|
||||
%cmp = icmp eq i32 %and, 0
|
||||
%sel = select i1 %cmp, i32 %y2, i32 %or
|
||||
ret i32 %sel
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue