PerformBFICombine - (bfi A, (and B, Mask1), Mask2) -> (bfi A, B, Mask2) iff

the bits being cleared by the AND are not demanded by the BFI.

The previous BFI dag combine rule was actually incorrect (or used to be
correct until BFI representation changed).

rdar://9609030


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133034 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2011-06-15 01:12:31 +00:00
parent cf886188fb
commit bf188aeae7
2 changed files with 20 additions and 4 deletions

View File

@ -5976,8 +5976,8 @@ static SDValue PerformORCombine(SDNode *N,
return SDValue();
}
/// PerformBFICombine - (bfi A, (and B, C1), C2) -> (bfi A, B, C2) iff
/// C1 & C2 == C1.
/// PerformBFICombine - (bfi A, (and B, Mask1), Mask2) -> (bfi A, B, Mask2) iff
/// the bits being cleared by the AND are not demanded by the BFI.
static SDValue PerformBFICombine(SDNode *N,
TargetLowering::DAGCombinerInfo &DCI) {
SDValue N1 = N->getOperand(1);
@ -5985,9 +5985,12 @@ static SDValue PerformBFICombine(SDNode *N,
ConstantSDNode *N11C = dyn_cast<ConstantSDNode>(N1.getOperand(1));
if (!N11C)
return SDValue();
unsigned Mask = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
unsigned InvMask = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
unsigned LSB = CountTrailingZeros_32(~InvMask);
unsigned Width = (32 - CountLeadingZeros_32(~InvMask)) - LSB;
unsigned Mask = (1 << Width)-1;
unsigned Mask2 = N11C->getZExtValue();
if ((Mask & Mask2) == Mask2)
if ((Mask & (~Mask2)) == 0)
return DCI.DAG.getNode(ARMISD::BFI, N->getDebugLoc(), N->getValueType(0),
N->getOperand(0), N1.getOperand(0),
N->getOperand(2));

View File

@ -61,3 +61,16 @@ entry:
%3 = or i32 %2, %0
ret i32 %3
}
; rdar://9609030
define i32 @f6(i32 %a, i32 %b) nounwind readnone {
entry:
; CHECK: f6:
; CHECK-NOT: bic
; CHECK: bfi r0, r1, #8, #9
%and = and i32 %a, -130817
%and2 = shl i32 %b, 8
%shl = and i32 %and2, 130816
%or = or i32 %shl, %and
ret i32 %or
}