Skip to content

Commit 5de09ef

Browse files
committed
[DAGCombiner][X86] Don't peek through ANDs on the shift amount in matchRotateSub when called from MatchFunnelPosNeg.
Peeking through AND is only valid if the input to both shifts is the same. If the inputs are different, then the original pattern ORs the two values when the masked shift amount is 0. This is ok if the values are the same since the OR would be a NOP which is why its ok for rotate. Fixes PR49365 and reverts PR34641 Differential Revision: https://reviews.llvm.org/D97637
1 parent b4bed1c commit 5de09ef

File tree

2 files changed

+40
-19
lines changed

2 files changed

+40
-19
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6630,8 +6630,11 @@ static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift,
66306630
// reduces to a rotate in direction shift2 by Pos or (equivalently) a rotate
66316631
// in direction shift1 by Neg. The range [0, EltSize) means that we only need
66326632
// to consider shift amounts with defined behavior.
6633+
//
6634+
// The IsRotate flag should be set when the LHS of both shifts is the same.
6635+
// Otherwise if matching a general funnel shift, it should be clear.
66336636
static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize,
6634-
SelectionDAG &DAG) {
6637+
SelectionDAG &DAG, bool IsRotate) {
66356638
// If EltSize is a power of 2 then:
66366639
//
66376640
// (a) (Pos == 0 ? 0 : EltSize - Pos) == (EltSize - Pos) & (EltSize - 1)
@@ -6663,8 +6666,11 @@ static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize,
66636666
// always invokes undefined behavior for 32-bit X.
66646667
//
66656668
// Below, Mask == EltSize - 1 when using [A] and is all-ones otherwise.
6669+
//
6670+
// NOTE: We can only do this when matching an AND and not a general
6671+
// funnel shift.
66666672
unsigned MaskLoBits = 0;
6667-
if (Neg.getOpcode() == ISD::AND && isPowerOf2_64(EltSize)) {
6673+
if (IsRotate && Neg.getOpcode() == ISD::AND && isPowerOf2_64(EltSize)) {
66686674
if (ConstantSDNode *NegC = isConstOrConstSplat(Neg.getOperand(1))) {
66696675
KnownBits Known = DAG.computeKnownBits(Neg.getOperand(0));
66706676
unsigned Bits = Log2_64(EltSize);
@@ -6754,7 +6760,8 @@ SDValue DAGCombiner::MatchRotatePosNeg(SDValue Shifted, SDValue Pos,
67546760
// (srl x, (*ext y))) ->
67556761
// (rotr x, y) or (rotl x, (sub 32, y))
67566762
EVT VT = Shifted.getValueType();
6757-
if (matchRotateSub(InnerPos, InnerNeg, VT.getScalarSizeInBits(), DAG)) {
6763+
if (matchRotateSub(InnerPos, InnerNeg, VT.getScalarSizeInBits(), DAG,
6764+
/*IsRotate*/ true)) {
67586765
bool HasPos = TLI.isOperationLegalOrCustom(PosOpcode, VT);
67596766
return DAG.getNode(HasPos ? PosOpcode : NegOpcode, DL, VT, Shifted,
67606767
HasPos ? Pos : Neg);
@@ -6783,7 +6790,7 @@ SDValue DAGCombiner::MatchFunnelPosNeg(SDValue N0, SDValue N1, SDValue Pos,
67836790
// fold (or (shl x0, (*ext (sub 32, y))),
67846791
// (srl x1, (*ext y))) ->
67856792
// (fshr x0, x1, y) or (fshl x0, x1, (sub 32, y))
6786-
if (matchRotateSub(InnerPos, InnerNeg, EltBits, DAG)) {
6793+
if (matchRotateSub(InnerPos, InnerNeg, EltBits, DAG, /*IsRotate*/ N0 == N1)) {
67876794
bool HasPos = TLI.isOperationLegalOrCustom(PosOpcode, VT);
67886795
return DAG.getNode(HasPos ? PosOpcode : NegOpcode, DL, VT, N0, N1,
67896796
HasPos ? Pos : Neg);

llvm/test/CodeGen/X86/shift-double.ll

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -480,23 +480,31 @@ define i32 @test18(i32 %hi, i32 %lo, i32 %bits) nounwind {
480480
ret i32 %sh
481481
}
482482

483-
; PR34641 - Masked Shift Counts
483+
; These are not valid shld/shrd patterns. When the shift amount modulo
484+
; the bitwidth is zero, the result should be an OR of both operands not a
485+
; shift.
484486

485-
define i32 @shld_safe_i32(i32, i32, i32) {
486-
; X86-LABEL: shld_safe_i32:
487+
define i32 @not_shld_i32(i32, i32, i32) {
488+
; X86-LABEL: not_shld_i32:
487489
; X86: # %bb.0:
490+
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
488491
; X86-NEXT: movb {{[0-9]+}}(%esp), %cl
489492
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
490-
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
491-
; X86-NEXT: shldl %cl, %edx, %eax
493+
; X86-NEXT: shll %cl, %edx
494+
; X86-NEXT: negb %cl
495+
; X86-NEXT: shrl %cl, %eax
496+
; X86-NEXT: orl %edx, %eax
492497
; X86-NEXT: retl
493498
;
494-
; X64-LABEL: shld_safe_i32:
499+
; X64-LABEL: not_shld_i32:
495500
; X64: # %bb.0:
496501
; X64-NEXT: movl %edx, %ecx
497-
; X64-NEXT: movl %edi, %eax
502+
; X64-NEXT: movl %esi, %eax
503+
; X64-NEXT: shll %cl, %edi
504+
; X64-NEXT: negb %cl
498505
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
499-
; X64-NEXT: shldl %cl, %esi, %eax
506+
; X64-NEXT: shrl %cl, %eax
507+
; X64-NEXT: orl %edi, %eax
500508
; X64-NEXT: retq
501509
%4 = and i32 %2, 31
502510
%5 = shl i32 %0, %4
@@ -507,21 +515,27 @@ define i32 @shld_safe_i32(i32, i32, i32) {
507515
ret i32 %9
508516
}
509517

510-
define i32 @shrd_safe_i32(i32, i32, i32) {
511-
; X86-LABEL: shrd_safe_i32:
518+
define i32 @not_shrd_i32(i32, i32, i32) {
519+
; X86-LABEL: not_shrd_i32:
512520
; X86: # %bb.0:
521+
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
513522
; X86-NEXT: movb {{[0-9]+}}(%esp), %cl
514523
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
515-
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
516-
; X86-NEXT: shrdl %cl, %edx, %eax
524+
; X86-NEXT: shrl %cl, %edx
525+
; X86-NEXT: negb %cl
526+
; X86-NEXT: shll %cl, %eax
527+
; X86-NEXT: orl %edx, %eax
517528
; X86-NEXT: retl
518529
;
519-
; X64-LABEL: shrd_safe_i32:
530+
; X64-LABEL: not_shrd_i32:
520531
; X64: # %bb.0:
521532
; X64-NEXT: movl %edx, %ecx
522-
; X64-NEXT: movl %edi, %eax
533+
; X64-NEXT: movl %esi, %eax
534+
; X64-NEXT: shrl %cl, %edi
535+
; X64-NEXT: negb %cl
523536
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
524-
; X64-NEXT: shrdl %cl, %esi, %eax
537+
; X64-NEXT: shll %cl, %eax
538+
; X64-NEXT: orl %edi, %eax
525539
; X64-NEXT: retq
526540
%4 = and i32 %2, 31
527541
%5 = lshr i32 %0, %4

0 commit comments

Comments
 (0)