[llvm] [Mips] Optimize `or (and $src1, mask0), (shl $src2, mask1)` to `ins` (PR #103017)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 4 19:11:10 PDT 2024
https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/103017
>From f26a32fa12504b4894274fc7a144aca68564a1e1 Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Fri, 2 Aug 2024 04:39:04 -0400
Subject: [PATCH] [Mips] Optimize `or (and $src1, mask0), (shl $src2, mask1)`
to `ins`
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Optimize `$dst = or (and $src1, (2**size0 - 1)), (shl $src2, size0)`
or `$dst = or (shl $src2, size0), (and $src1, (2**size0 - 1))`
to `ins $src1, $src2, pos, size, pos = size0, size = 32 – pos`.
Fix #90325
---
llvm/lib/Target/Mips/MipsISelLowering.cpp | 47 ++++++++++++++++--
llvm/test/CodeGen/Mips/ins.ll | 60 +++++++++++++++++++++++
2 files changed, 103 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/Mips/ins.ll
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 0f2047fcac640e..0a76275d4008d2 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -876,21 +876,60 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget &Subtarget) {
- // Pattern match INS.
- // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
- // where mask1 = (2**size - 1) << pos, mask0 = ~mask1
- // => ins $dst, $src, size, pos, $src1
if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert())
return SDValue();
SDValue And0 = N->getOperand(0), And1 = N->getOperand(1);
unsigned SMPos0, SMSize0, SMPos1, SMSize1;
ConstantSDNode *CN, *CN1;
+ uint64_t Pos = 0;
+
+ if ((And0.getOpcode() == ISD::AND && And1.getOpcode() == ISD::SHL) ||
+ (And0.getOpcode() == ISD::SHL && And1.getOpcode() == ISD::AND)) {
+ // Pattern match INS.
+ // $dst = or (and $src1, (2**size0 - 1)), (shl $src2, size0)
+ // ==> ins $src1, $src2, pos, size, pos = size0, size = 32 - pos;
+ // Or:
+ // $dst = or (shl $src2, size0), (and $src1, (2**size0 - 1))
+ // ==> ins $src1, $src2, pos, size, pos = size0, size = 32 - pos;
+ SDValue Operand =
+ And0.getOpcode() == ISD::AND ? And0.getOperand(1) : And1.getOperand(1);
+ if (!(CN = dyn_cast<ConstantSDNode>(Operand)) ||
+ !isShiftedMask_64(CN->getZExtValue(), SMPos0, SMSize0))
+ return SDValue();
+
+ Operand =
+ And0.getOpcode() == ISD::AND ? And1.getOperand(1) : And0.getOperand(1);
+ if (!(CN = dyn_cast<ConstantSDNode>(Operand)))
+ return SDValue();
+ Pos = CN->getZExtValue();
+
+ if (SMPos0 != 0 || SMSize0 != Pos)
+ return SDValue();
+
+ SDLoc DL(N);
+ EVT ValTy = N->getValueType(0);
+ SMPos1 = Pos;
+ SMSize1 = (ValTy == MVT::i64 ? 64 : 32) - SMPos1;
+ return And0.getOpcode() == ISD::AND
+ ? DAG.getNode(MipsISD::Ins, DL, ValTy, And1.getOperand(0),
+ DAG.getConstant(SMPos1, DL, MVT::i32),
+ DAG.getConstant(SMSize1, DL, MVT::i32),
+ And0.getOperand(0))
+ : DAG.getNode(MipsISD::Ins, DL, ValTy, And0.getOperand(0),
+ DAG.getConstant(SMPos1, DL, MVT::i32),
+ DAG.getConstant(SMSize1, DL, MVT::i32),
+ And1.getOperand(0));
+ }
// See if Op's first operand matches (and $src1 , mask0).
if (And0.getOpcode() != ISD::AND)
return SDValue();
+ // Pattern match INS.
+ // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
+ // where mask1 = (2**size - 1) << pos, mask0 = ~mask1
+ // => ins $dst, $src, size, pos, $src1
if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) ||
!isShiftedMask_64(~CN->getSExtValue(), SMPos0, SMSize0))
return SDValue();
diff --git a/llvm/test/CodeGen/Mips/ins.ll b/llvm/test/CodeGen/Mips/ins.ll
new file mode 100644
index 00000000000000..615dc8f3d6ac5a
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/ins.ll
@@ -0,0 +1,60 @@
+; RUN: llc -O3 -mcpu=mips32r2 -mtriple=mipsel-linux-gnu < %s -o - \
+; RUN: | FileCheck %s --check-prefixes=MIPS32R2
+; RUN: llc -O3 -mcpu=mips64r2 -march=mips64el < %s \
+; RUN: | FileCheck %s --check-prefixes=MIPS64R2
+
+define i32 @or_and_shl(i32 %a, i32 %b) {
+; MIPS32R2-LABEL: or_and_shl:
+; MIPS32R2: # %bb.0: # %entry
+; MIPS32R2-NEXT: ins $4, $5, 31, 1
+; MIPS32R2-NEXT: jr $ra
+; MIPS32R2-NEXT: move $2, $4
+
+entry:
+ %shl = shl i32 %b, 31
+ %and = and i32 %a, 2147483647
+ %or = or i32 %and, %shl
+ ret i32 %or
+}
+
+define i32 @or_shl_and(i32 %a, i32 %b) {
+; MIPS32R2-LABEL: or_shl_and:
+; MIPS32R2: # %bb.0: # %entry
+; MIPS32R2-NEXT: ins $4, $5, 31, 1
+; MIPS32R2-NEXT: jr $ra
+; MIPS32R2-NEXT: move $2, $4
+
+entry:
+ %shl = shl i32 %b, 31
+ %and = and i32 %a, 2147483647
+ %or = or i32 %shl, %and
+ ret i32 %or
+}
+
+define i64 @dinsm(i64 %a, i64 %b) {
+; MIPS64R2-LABEL: dinsm:
+; MIPS64R2: # %bb.0: # %entry
+; MIPS64R2-NEXT: dinsm $4, $5, 17, 47
+; MIPS64R2-NEXT: jr $ra
+; MIPS64R2-NEXT: move $2, $4
+
+entry:
+ %shl = shl i64 %b, 17
+ %and = and i64 %a, 131071
+ %or = or i64 %shl, %and
+ ret i64 %or
+}
+
+define i64 @dinsu(i64 %a, i64 %b) {
+; MIPS64R2-LABEL: dinsu:
+; MIPS64R2: # %bb.0: # %entry
+; MIPS64R2-NEXT: dinsu $4, $5, 35, 29
+; MIPS64R2-NEXT: jr $ra
+; MIPS64R2-NEXT: move $2, $4
+
+entry:
+ %shl = shl i64 %b, 35
+ %and = and i64 %a, 34359738367
+ %or = or i64 %shl, %and
+ ret i64 %or
+}
More information about the llvm-commits
mailing list