Skip to content

Commit d7c80bb

Browse files
authored
[llvm][LoongArch] Improve loongarch_lasx_xvpermi_q instrinsic (#82984)
For instruction xvpermi.q, only [1:0] and [5:4] bits of operands[3] are used. The unused bits in operands[3] need to be set to 0 to avoid causing undefined behavior.
1 parent ed1aabe commit d7c80bb

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

+24-1
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,28 @@ static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp,
968968
return SDValue();
969969
}
970970

971+
static SDValue checkAndModifyXVPERMI_QIntrinsicImmArg(SDValue Op,
972+
SelectionDAG &DAG) {
973+
SDValue Op3 = Op->getOperand(3);
974+
uint64_t Imm = Op3->getAsZExtVal();
975+
// Check the range of ImmArg.
976+
if (!isUInt<8>(Imm)) {
977+
DAG.getContext()->emitError(Op->getOperationName(0) +
978+
": argument out of range.");
979+
return DAG.getNode(ISD::UNDEF, SDLoc(Op), Op.getValueType());
980+
}
981+
982+
// For instruction xvpermi.q, only [1:0] and [5:4] bits of operands[3]
983+
// are used. The unused bits in operands[3] need to be set to 0 to avoid
984+
// causing undefined behavior on LA464.
985+
if ((Imm & 0x33) != Imm) {
986+
Op3 = DAG.getTargetConstant(Imm & 0x33, SDLoc(Op), Op3.getValueType());
987+
DAG.UpdateNodeOperands(Op.getNode(), Op->getOperand(0), Op->getOperand(1),
988+
Op->getOperand(2), Op3);
989+
}
990+
return SDValue();
991+
}
992+
971993
SDValue
972994
LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
973995
SelectionDAG &DAG) const {
@@ -1225,13 +1247,14 @@ LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
12251247
case Intrinsic::loongarch_lsx_vextrins_d:
12261248
case Intrinsic::loongarch_lasx_xvshuf4i_d:
12271249
case Intrinsic::loongarch_lasx_xvpermi_w:
1228-
case Intrinsic::loongarch_lasx_xvpermi_q:
12291250
case Intrinsic::loongarch_lasx_xvbitseli_b:
12301251
case Intrinsic::loongarch_lasx_xvextrins_b:
12311252
case Intrinsic::loongarch_lasx_xvextrins_h:
12321253
case Intrinsic::loongarch_lasx_xvextrins_w:
12331254
case Intrinsic::loongarch_lasx_xvextrins_d:
12341255
return checkIntrinsicImmArg<8>(Op, 3, DAG);
1256+
case Intrinsic::loongarch_lasx_xvpermi_q:
1257+
return checkAndModifyXVPERMI_QIntrinsicImmArg(Op, DAG);
12351258
case Intrinsic::loongarch_lsx_vrepli_b:
12361259
case Intrinsic::loongarch_lsx_vrepli_h:
12371260
case Intrinsic::loongarch_lsx_vrepli_w:

llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll

+30
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,33 @@ entry:
3636
%res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 1)
3737
ret <32 x i8> %res
3838
}
39+
40+
define <32 x i8> @lasx_xvpermi_q_204(<32 x i8> %va, <32 x i8> %vb) nounwind {
41+
; CHECK-LABEL: lasx_xvpermi_q_204:
42+
; CHECK: # %bb.0: # %entry
43+
; CHECK-NEXT: xvpermi.q $xr0, $xr1, 0
44+
; CHECK-NEXT: ret
45+
entry:
46+
%res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 204)
47+
ret <32 x i8> %res
48+
}
49+
50+
define <32 x i8> @lasx_xvpermi_q_221(<32 x i8> %va, <32 x i8> %vb) nounwind {
51+
; CHECK-LABEL: lasx_xvpermi_q_221:
52+
; CHECK: # %bb.0: # %entry
53+
; CHECK-NEXT: xvpermi.q $xr0, $xr1, 17
54+
; CHECK-NEXT: ret
55+
entry:
56+
%res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 221)
57+
ret <32 x i8> %res
58+
}
59+
60+
define <32 x i8> @lasx_xvpermi_q_255(<32 x i8> %va, <32 x i8> %vb) nounwind {
61+
; CHECK-LABEL: lasx_xvpermi_q_255:
62+
; CHECK: # %bb.0: # %entry
63+
; CHECK-NEXT: xvpermi.q $xr0, $xr1, 51
64+
; CHECK-NEXT: ret
65+
entry:
66+
%res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 255)
67+
ret <32 x i8> %res
68+
}

0 commit comments

Comments
 (0)