[llvm] 6affe87 - [DAGCombiner] When matching a disguised rotate by constant don't forget to apply LHSMask/RHSMask.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 30 11:16:43 PDT 2022
Author: Craig Topper
Date: 2022-04-30T11:02:30-07:00
New Revision: 6affe87bda203b6d6538f41bb44879509962c695
URL: https://github.com/llvm/llvm-project/commit/6affe87bda203b6d6538f41bb44879509962c695
DIFF: https://github.com/llvm/llvm-project/commit/6affe87bda203b6d6538f41bb44879509962c695.diff
LOG: [DAGCombiner] When matching a disguised rotate by constant don't forget to apply LHSMask/RHSMask.
We try to match as a disguised rotate by constant of these forms
(shl (X | Y), C1) | (srl X, C2) --> (rotl X, C1) | (shl Y, C1)
(shl X, C1) | (srl (X | Y), C2) --> (rotl X, C1) | (srl Y, C2)
We may have also looked through an AND to find the shift. If we
did, we need to apply a mask to the result.
I'll add an AArch64 test and pre-commit it and the RISC-V test
tomorrow.
Fixes PR55201.
Reviewed By: RKSimon
Differential Revision: https://reviews.llvm.org/D124711
Added:
Modified:
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/AArch64/pr55201.ll
llvm/test/CodeGen/RISCV/pr55201.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 5f964c08b28ec..13ea53723ebef 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -7480,6 +7480,29 @@ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
return (LHS->getAPIntValue() + RHS->getAPIntValue()) == EltSizeInBits;
};
+ auto ApplyMasks = [&](SDValue Res) {
+ // If there is an AND of either shifted operand, apply it to the result.
+ if (LHSMask.getNode() || RHSMask.getNode()) {
+ SDValue AllOnes = DAG.getAllOnesConstant(DL, VT);
+ SDValue Mask = AllOnes;
+
+ if (LHSMask.getNode()) {
+ SDValue RHSBits = DAG.getNode(ISD::SRL, DL, VT, AllOnes, RHSShiftAmt);
+ Mask = DAG.getNode(ISD::AND, DL, VT, Mask,
+ DAG.getNode(ISD::OR, DL, VT, LHSMask, RHSBits));
+ }
+ if (RHSMask.getNode()) {
+ SDValue LHSBits = DAG.getNode(ISD::SHL, DL, VT, AllOnes, LHSShiftAmt);
+ Mask = DAG.getNode(ISD::AND, DL, VT, Mask,
+ DAG.getNode(ISD::OR, DL, VT, RHSMask, LHSBits));
+ }
+
+ Res = DAG.getNode(ISD::AND, DL, VT, Res, Mask);
+ }
+
+ return Res;
+ };
+
// TODO: Support pre-legalization funnel-shift by constant.
bool IsRotate = LHSShift.getOperand(0) == RHSShift.getOperand(0);
if (!IsRotate && !(HasFSHL || HasFSHR)) {
@@ -7504,18 +7527,21 @@ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
return false;
};
- // (shl (X | Y), C1) | (srl X, C2) --> (rotl X, C1) | (shl Y, C1)
+ SDValue Res;
if (matchOr(LHSShiftArg, RHSShiftArg)) {
+ // (shl (X | Y), C1) | (srl X, C2) --> (rotl X, C1) | (shl Y, C1)
SDValue RotX = DAG.getNode(ISD::ROTL, DL, VT, X, LHSShiftAmt);
SDValue ShlY = DAG.getNode(ISD::SHL, DL, VT, Y, LHSShiftAmt);
- return DAG.getNode(ISD::OR, DL, VT, RotX, ShlY);
- }
- // (shl X, C1) | (srl (X | Y), C2) --> (rotl X, C1) | (srl Y, C2)
- if (matchOr(RHSShiftArg, LHSShiftArg)) {
+ Res = DAG.getNode(ISD::OR, DL, VT, RotX, ShlY);
+ } else if (matchOr(RHSShiftArg, LHSShiftArg)) {
+ // (shl X, C1) | (srl (X | Y), C2) --> (rotl X, C1) | (srl Y, C2)
SDValue RotX = DAG.getNode(ISD::ROTL, DL, VT, X, LHSShiftAmt);
SDValue SrlY = DAG.getNode(ISD::SRL, DL, VT, Y, RHSShiftAmt);
- return DAG.getNode(ISD::OR, DL, VT, RotX, SrlY);
- }
+ Res = DAG.getNode(ISD::OR, DL, VT, RotX, SrlY);
+ } else
+ return SDValue();
+
+ return ApplyMasks(Res);
}
return SDValue(); // Requires funnel shift support.
@@ -7538,26 +7564,7 @@ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
RHSShiftArg, UseFSHL ? LHSShiftAmt : RHSShiftAmt);
}
- // If there is an AND of either shifted operand, apply it to the result.
- if (LHSMask.getNode() || RHSMask.getNode()) {
- SDValue AllOnes = DAG.getAllOnesConstant(DL, VT);
- SDValue Mask = AllOnes;
-
- if (LHSMask.getNode()) {
- SDValue RHSBits = DAG.getNode(ISD::SRL, DL, VT, AllOnes, RHSShiftAmt);
- Mask = DAG.getNode(ISD::AND, DL, VT, Mask,
- DAG.getNode(ISD::OR, DL, VT, LHSMask, RHSBits));
- }
- if (RHSMask.getNode()) {
- SDValue LHSBits = DAG.getNode(ISD::SHL, DL, VT, AllOnes, LHSShiftAmt);
- Mask = DAG.getNode(ISD::AND, DL, VT, Mask,
- DAG.getNode(ISD::OR, DL, VT, RHSMask, LHSBits));
- }
-
- Res = DAG.getNode(ISD::AND, DL, VT, Res, Mask);
- }
-
- return Res;
+ return ApplyMasks(Res);
}
// Even pre-legalization, we can't easily rotate/funnel-shift by a variable
diff --git a/llvm/test/CodeGen/AArch64/pr55201.ll b/llvm/test/CodeGen/AArch64/pr55201.ll
index 52f7cc0b708d5..44c42d3836565 100644
--- a/llvm/test/CodeGen/AArch64/pr55201.ll
+++ b/llvm/test/CodeGen/AArch64/pr55201.ll
@@ -5,7 +5,8 @@ define i32 @f(i32 %x) {
; CHECK-LABEL: f:
; CHECK: // %bb.0:
; CHECK-NEXT: ror w8, w0, #27
-; CHECK-NEXT: orr w0, w8, #0x20
+; CHECK-NEXT: orr w8, w8, #0x20
+; CHECK-NEXT: and w0, w8, #0xffffffe1
; CHECK-NEXT: ret
%or1 = or i32 %x, 1
%sh1 = shl i32 %or1, 5
diff --git a/llvm/test/CodeGen/RISCV/pr55201.ll b/llvm/test/CodeGen/RISCV/pr55201.ll
index 7dc9c378a14a1..63200de9c0c77 100644
--- a/llvm/test/CodeGen/RISCV/pr55201.ll
+++ b/llvm/test/CodeGen/RISCV/pr55201.ll
@@ -6,6 +6,7 @@ define i32 @f(i32 %x) {
; CHECK: # %bb.0:
; CHECK-NEXT: rori a0, a0, 27
; CHECK-NEXT: ori a0, a0, 32
+; CHECK-NEXT: andi a0, a0, -31
; CHECK-NEXT: ret
%or1 = or i32 %x, 1
%sh1 = shl i32 %or1, 5
More information about the llvm-commits
mailing list