Skip to content

Commit 4dd87cd

Browse files
committed
X86: make VBMI2 funnel shifts use VSHLD/VSHRD for const splats
Move constant splat handling for vector funnel shifts into a DAG combiner so that VBMI2 legal widths emit VSHLD/VSHRD directly (fixes #166949). Signed-off-by: Arnav Mehta <[email protected]>
1 parent 79c56e8 commit 4dd87cd

File tree

1 file changed

+43
-4
lines changed

1 file changed

+43
-4
lines changed

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,8 +2073,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
20732073

20742074
if (Subtarget.hasVBMI2()) {
20752075
for (auto VT : {MVT::v32i16, MVT::v16i32, MVT::v8i64}) {
2076-
setOperationAction(ISD::FSHL, VT, Custom);
2077-
setOperationAction(ISD::FSHR, VT, Custom);
2076+
setOperationAction(ISD::FSHL, VT, Legal);
2077+
setOperationAction(ISD::FSHR, VT, Legal);
20782078
}
20792079

20802080
setOperationAction(ISD::ROTL, MVT::v32i16, Custom);
@@ -2089,8 +2089,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
20892089
if (!Subtarget.useSoftFloat() && Subtarget.hasVBMI2()) {
20902090
for (auto VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v16i16, MVT::v8i32,
20912091
MVT::v4i64}) {
2092-
setOperationAction(ISD::FSHL, VT, Custom);
2093-
setOperationAction(ISD::FSHR, VT, Custom);
2092+
setOperationAction(ISD::FSHL, VT, Subtarget.hasVLX() ? Legal : Custom);
2093+
setOperationAction(ISD::FSHR, VT, Subtarget.hasVLX() ? Legal : Custom);
20942094
}
20952095
}
20962096

@@ -2703,6 +2703,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
27032703
ISD::STRICT_FP_EXTEND,
27042704
ISD::FP_ROUND,
27052705
ISD::STRICT_FP_ROUND,
2706+
ISD::FSHL,
2707+
ISD::FSHR,
27062708
ISD::INTRINSIC_VOID,
27072709
ISD::INTRINSIC_WO_CHAIN,
27082710
ISD::INTRINSIC_W_CHAIN});
@@ -57624,6 +57626,41 @@ static SDValue combineFP_TO_xINT_SAT(SDNode *N, SelectionDAG &DAG,
5762457626
return SDValue();
5762557627
}
5762657628

57629+
// Combiner: turn uniform-constant splat funnel shifts into VSHLD/VSHRD
57630+
static SDValue combineFunnelShift(SDNode *N, SelectionDAG &DAG,
57631+
TargetLowering::DAGCombinerInfo &DCI,
57632+
const X86Subtarget &Subtarget) {
57633+
SDLoc DL(N);
57634+
SDValue Op0 = N->getOperand(0);
57635+
SDValue Op1 = N->getOperand(1);
57636+
SDValue Amt = N->getOperand(2);
57637+
EVT VT = Op0.getValueType();
57638+
57639+
if (!VT.isVector())
57640+
return SDValue();
57641+
57642+
// Only combine if the operation is legal for this type.
57643+
// This ensures we don't try to convert types that need to be
57644+
// widened/promoted.
57645+
if (!DAG.getTargetLoweringInfo().isOperationLegal(N->getOpcode(), VT))
57646+
return SDValue();
57647+
57648+
unsigned EltSize = VT.getScalarSizeInBits();
57649+
APInt ShiftVal;
57650+
if (!X86::isConstantSplat(Amt, ShiftVal))
57651+
return SDValue();
57652+
57653+
uint64_t ModAmt = ShiftVal.urem(EltSize);
57654+
SDValue Imm = DAG.getTargetConstant(ModAmt, DL, MVT::i8);
57655+
bool IsFSHR = N->getOpcode() == ISD::FSHR;
57656+
57657+
if (IsFSHR)
57658+
std::swap(Op0, Op1);
57659+
unsigned Opcode = IsFSHR ? X86ISD::VSHRD : X86ISD::VSHLD;
57660+
57661+
return DAG.getNode(Opcode, DL, VT, {Op0, Op1, Imm});
57662+
}
57663+
5762757664
static bool needCarryOrOverflowFlag(SDValue Flags) {
5762857665
assert(Flags.getValueType() == MVT::i32 && "Unexpected VT!");
5762957666

@@ -61228,6 +61265,8 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
6122861265
case ISD::INTRINSIC_VOID: return combineINTRINSIC_VOID(N, DAG, DCI);
6122961266
case ISD::FP_TO_SINT_SAT:
6123061267
case ISD::FP_TO_UINT_SAT: return combineFP_TO_xINT_SAT(N, DAG, Subtarget);
61268+
case ISD::FSHL:
61269+
case ISD::FSHR: return combineFunnelShift(N, DAG, DCI, Subtarget);
6123161270
// clang-format on
6123261271
}
6123361272

0 commit comments

Comments
 (0)