Skip to content

Commit 1ad84d7

Browse files
authored
[Mips] Optimize or (and $src1, mask), (shl $src2, shift) to ins (llvm#103017)
Optimize `$dst = or (and $src1, (2**size0 - 1)), (shl $src2, size0)` to `ins $src1, $src2, pos, size`, where `pos = size0, size = 32 - pos`. Fix llvm#90325
1 parent 7353507 commit 1ad84d7

File tree

2 files changed

+121
-18
lines changed

2 files changed

+121
-18
lines changed

llvm/lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -880,38 +880,81 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
880880
static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
881881
TargetLowering::DAGCombinerInfo &DCI,
882882
const MipsSubtarget &Subtarget) {
883-
// Pattern match INS.
884-
// $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
885-
// where mask1 = (2**size - 1) << pos, mask0 = ~mask1
886-
// => ins $dst, $src, size, pos, $src1
887883
if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert())
888884
return SDValue();
889885

890-
SDValue And0 = N->getOperand(0), And1 = N->getOperand(1);
886+
SDValue FirstOperand = N->getOperand(0), SecondOperand = N->getOperand(1);
891887
unsigned SMPos0, SMSize0, SMPos1, SMSize1;
892888
ConstantSDNode *CN, *CN1;
893889

890+
if ((FirstOperand.getOpcode() == ISD::AND &&
891+
SecondOperand.getOpcode() == ISD::SHL) ||
892+
(FirstOperand.getOpcode() == ISD::SHL &&
893+
SecondOperand.getOpcode() == ISD::AND)) {
894+
// Pattern match INS.
895+
// $dst = or (and $src1, (2**size0 - 1)), (shl $src2, size0)
896+
// ==> ins $src1, $src2, pos, size, pos = size0, size = 32 - pos;
897+
// Or:
898+
// $dst = or (shl $src2, size0), (and $src1, (2**size0 - 1))
899+
// ==> ins $src1, $src2, pos, size, pos = size0, size = 32 - pos;
900+
SDValue AndOperand0 = FirstOperand.getOpcode() == ISD::AND
901+
? FirstOperand.getOperand(0)
902+
: SecondOperand.getOperand(0);
903+
SDValue ShlOperand0 = FirstOperand.getOpcode() == ISD::AND
904+
? SecondOperand.getOperand(0)
905+
: FirstOperand.getOperand(0);
906+
SDValue AndMask = FirstOperand.getOpcode() == ISD::AND
907+
? FirstOperand.getOperand(1)
908+
: SecondOperand.getOperand(1);
909+
if (!(CN = dyn_cast<ConstantSDNode>(AndMask)) ||
910+
!isShiftedMask_64(CN->getZExtValue(), SMPos0, SMSize0))
911+
return SDValue();
912+
913+
SDValue ShlShift = FirstOperand.getOpcode() == ISD::AND
914+
? SecondOperand.getOperand(1)
915+
: FirstOperand.getOperand(1);
916+
if (!(CN = dyn_cast<ConstantSDNode>(ShlShift)))
917+
return SDValue();
918+
uint64_t ShlShiftValue = CN->getZExtValue();
919+
920+
if (SMPos0 != 0 || SMSize0 != ShlShiftValue)
921+
return SDValue();
922+
923+
SDLoc DL(N);
924+
EVT ValTy = N->getValueType(0);
925+
SMPos1 = ShlShiftValue;
926+
assert(SMPos1 < ValTy.getSizeInBits());
927+
SMSize1 = (ValTy == MVT::i64 ? 64 : 32) - SMPos1;
928+
return DAG.getNode(MipsISD::Ins, DL, ValTy, ShlOperand0,
929+
DAG.getConstant(SMPos1, DL, MVT::i32),
930+
DAG.getConstant(SMSize1, DL, MVT::i32), AndOperand0);
931+
}
932+
894933
// See if Op's first operand matches (and $src1 , mask0).
895-
if (And0.getOpcode() != ISD::AND)
934+
if (FirstOperand.getOpcode() != ISD::AND)
896935
return SDValue();
897936

898-
if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) ||
937+
// Pattern match INS.
938+
// $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
939+
// where mask1 = (2**size - 1) << pos, mask0 = ~mask1
940+
// => ins $dst, $src, size, pos, $src1
941+
if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||
899942
!isShiftedMask_64(~CN->getSExtValue(), SMPos0, SMSize0))
900943
return SDValue();
901944

902945
// See if Op's second operand matches (and (shl $src, pos), mask1).
903-
if (And1.getOpcode() == ISD::AND &&
904-
And1.getOperand(0).getOpcode() == ISD::SHL) {
946+
if (SecondOperand.getOpcode() == ISD::AND &&
947+
SecondOperand.getOperand(0).getOpcode() == ISD::SHL) {
905948

906-
if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
949+
if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand.getOperand(1))) ||
907950
!isShiftedMask_64(CN->getZExtValue(), SMPos1, SMSize1))
908951
return SDValue();
909952

910953
// The shift masks must have the same position and size.
911954
if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
912955
return SDValue();
913956

914-
SDValue Shl = And1.getOperand(0);
957+
SDValue Shl = SecondOperand.getOperand(0);
915958

916959
if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
917960
return SDValue();
@@ -928,7 +971,7 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
928971
return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0),
929972
DAG.getConstant(SMPos0, DL, MVT::i32),
930973
DAG.getConstant(SMSize0, DL, MVT::i32),
931-
And0.getOperand(0));
974+
FirstOperand.getOperand(0));
932975
} else {
933976
// Pattern match DINS.
934977
// $dst = or (and $src, mask0), mask1
@@ -938,9 +981,9 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
938981
((SMSize0 + SMPos0 <= 64 && Subtarget.hasMips64r2()) ||
939982
(SMSize0 + SMPos0 <= 32))) {
940983
// Check if AND instruction has constant as argument
941-
bool isConstCase = And1.getOpcode() != ISD::AND;
942-
if (And1.getOpcode() == ISD::AND) {
943-
if (!(CN1 = dyn_cast<ConstantSDNode>(And1->getOperand(1))))
984+
bool isConstCase = SecondOperand.getOpcode() != ISD::AND;
985+
if (SecondOperand.getOpcode() == ISD::AND) {
986+
if (!(CN1 = dyn_cast<ConstantSDNode>(SecondOperand->getOperand(1))))
944987
return SDValue();
945988
} else {
946989
if (!(CN1 = dyn_cast<ConstantSDNode>(N->getOperand(1))))
@@ -957,7 +1000,8 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
9571000
SDValue SrlX;
9581001
if (!isConstCase) {
9591002
Const1 = DAG.getConstant(SMPos0, DL, MVT::i32);
960-
SrlX = DAG.getNode(ISD::SRL, DL, And1->getValueType(0), And1, Const1);
1003+
SrlX = DAG.getNode(ISD::SRL, DL, SecondOperand->getValueType(0),
1004+
SecondOperand, Const1);
9611005
}
9621006
return DAG.getNode(
9631007
MipsISD::Ins, DL, N->getValueType(0),
@@ -968,8 +1012,7 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
9681012
DAG.getConstant(ValTy.getSizeInBits() / 8 < 8 ? SMSize0 & 31
9691013
: SMSize0,
9701014
DL, MVT::i32),
971-
And0->getOperand(0));
972-
1015+
FirstOperand->getOperand(0));
9731016
}
9741017
return SDValue();
9751018
}

llvm/test/CodeGen/Mips/ins.ll

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; RUN: llc -O3 -mcpu=mips32r2 -mtriple=mipsel-linux-gnu < %s -o - \
2+
; RUN: | FileCheck %s --check-prefixes=MIPS32R2
3+
; RUN: llc -O3 -mcpu=mips64r2 -march=mips64el < %s \
4+
; RUN: | FileCheck %s --check-prefixes=MIPS64R2
5+
6+
define i32 @or_and_shl(i32 %a, i32 %b) {
7+
; MIPS32R2-LABEL: or_and_shl:
8+
; MIPS32R2: # %bb.0: # %entry
9+
; MIPS32R2-NEXT: ins $4, $5, 31, 1
10+
; MIPS32R2-NEXT: jr $ra
11+
; MIPS32R2-NEXT: move $2, $4
12+
13+
entry:
14+
%shl = shl i32 %b, 31
15+
%and = and i32 %a, 2147483647
16+
%or = or i32 %and, %shl
17+
ret i32 %or
18+
}
19+
20+
define i32 @or_shl_and(i32 %a, i32 %b) {
21+
; MIPS32R2-LABEL: or_shl_and:
22+
; MIPS32R2: # %bb.0: # %entry
23+
; MIPS32R2-NEXT: ins $4, $5, 31, 1
24+
; MIPS32R2-NEXT: jr $ra
25+
; MIPS32R2-NEXT: move $2, $4
26+
27+
entry:
28+
%shl = shl i32 %b, 31
29+
%and = and i32 %a, 2147483647
30+
%or = or i32 %shl, %and
31+
ret i32 %or
32+
}
33+
34+
define i64 @dinsm(i64 %a, i64 %b) {
35+
; MIPS64R2-LABEL: dinsm:
36+
; MIPS64R2: # %bb.0: # %entry
37+
; MIPS64R2-NEXT: dinsm $4, $5, 17, 47
38+
; MIPS64R2-NEXT: jr $ra
39+
; MIPS64R2-NEXT: move $2, $4
40+
41+
entry:
42+
%shl = shl i64 %b, 17
43+
%and = and i64 %a, 131071
44+
%or = or i64 %shl, %and
45+
ret i64 %or
46+
}
47+
48+
define i64 @dinsu(i64 %a, i64 %b) {
49+
; MIPS64R2-LABEL: dinsu:
50+
; MIPS64R2: # %bb.0: # %entry
51+
; MIPS64R2-NEXT: dinsu $4, $5, 35, 29
52+
; MIPS64R2-NEXT: jr $ra
53+
; MIPS64R2-NEXT: move $2, $4
54+
55+
entry:
56+
%shl = shl i64 %b, 35
57+
%and = and i64 %a, 34359738367
58+
%or = or i64 %shl, %and
59+
ret i64 %or
60+
}

0 commit comments

Comments
 (0)