From 22b0c021254f4533ce8039f5d21bf2d21f8529d8 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Sun, 15 Aug 2021 14:24:20 +0100 Subject: [PATCH] [DAGCombiner] Stop visitEXTRACT_SUBVECTOR creating illegal BITCASTs post legalisation. visitEXTRACT_SUBVECTOR can sometimes create illegal BITCASTs when removing "redundant" INSERT_SUBVECTOR operations. This patch adds an extra check to ensure such combines only occur after operation legalisation if any resulting BITBAST is itself legal. Differential Revision: https://reviews.llvm.org/D108086 (cherry picked from commit cd0e1964137f1cd7b508809ec80c7d9dcb3f0458) --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 6 +++- .../sve-fixed-length-masked-scatter.ll | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 1bba7232eb1..4f730b2cf37 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -20560,8 +20560,12 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *N) { // otherwise => (extract_subvec V1, ExtIdx) uint64_t InsIdx = V.getConstantOperandVal(2); if (InsIdx * SmallVT.getScalarSizeInBits() == - ExtIdx * NVT.getScalarSizeInBits()) + ExtIdx * NVT.getScalarSizeInBits()) { + if (LegalOperations && !TLI.isOperationLegal(ISD::BITCAST, NVT)) + return SDValue(); + return DAG.getBitcast(NVT, V.getOperand(1)); + } return DAG.getNode( ISD::EXTRACT_SUBVECTOR, SDLoc(N), NVT, DAG.getBitcast(N->getOperand(0).getValueType(), V.getOperand(0)), diff --git a/test/CodeGen/AArch64/sve-fixed-length-masked-scatter.ll b/test/CodeGen/AArch64/sve-fixed-length-masked-scatter.ll index ec0f4bdf025..2ce98f00687 100644 --- a/test/CodeGen/AArch64/sve-fixed-length-masked-scatter.ll +++ b/test/CodeGen/AArch64/sve-fixed-length-masked-scatter.ll @@ -1057,6 +1057,37 @@ define void @masked_scatter_vec_plus_imm(<32 x float>* %a, <32 x i8*>* %b) #0 { ret void } +; extract_subvec(...(insert_subvec(a,b,c))) -> extract_subvec(bitcast(b),d) like +; combines can effectively unlegalise bitcast operations. This test ensures such +; combines do not happen after operation legalisation. When not prevented the +; test triggers infinite combine->legalise->combine->... +; +; NOTE: For this test to function correctly it's critical for %vals to be in a +; different block to the scatter store. If not, the problematic bitcast will be +; removed before operation legalisation and thus not exercise the combine. +define void @masked_scatter_bitcast_infinite_loop(<8 x double>* %a, <8 x double*>* %b, i1 %cond) #0 { +; CHECK-LABEL: masked_scatter_bitcast_infinite_loop +; VBITS_GE_512: ptrue [[PG0:p[0-9]+]].d, vl8 +; VBITS_GE_512-NEXT: ld1d { [[VALS:z[0-9]+]].d }, [[PG0]]/z, [x0] +; VBITS_GE_512-NEXT: tbz w2, #0, [[LABEL:.*]] +; VBITS_GE_512-NEXT: ld1d { [[PTRS:z[0-9]+]].d }, [[PG0]]/z, [x1] +; VBITS_GE_512-NEXT: fcmeq [[MASK:p[0-9]+]].d, [[PG0]]/z, [[VALS]].d, #0.0 +; VBITS_GE_512-NEXT: st1d { [[VALS]].d }, [[MASK]], {{\[}}[[PTRS]].d] +; VBITS_GE_512-NEXT: [[LABEL]]: +; VBITS_GE_512-NEXT: ret + %vals = load volatile <8 x double>, <8 x double>* %a + br i1 %cond, label %bb.1, label %bb.2 + +bb.1: + %ptrs = load <8 x double*>, <8 x double*>* %b + %mask = fcmp oeq <8 x double> %vals, zeroinitializer + call void @llvm.masked.scatter.v8f64(<8 x double> %vals, <8 x double*> %ptrs, i32 8, <8 x i1> %mask) + br label %bb.2 + +bb.2: + ret void +} + declare void @llvm.masked.scatter.v2i8(<2 x i8>, <2 x i8*>, i32, <2 x i1>) declare void @llvm.masked.scatter.v4i8(<4 x i8>, <4 x i8*>, i32, <4 x i1>) declare void @llvm.masked.scatter.v8i8(<8 x i8>, <8 x i8*>, i32, <8 x i1>)