From 5a44777de2a296795d71abefcfd17ac92c00808b Mon Sep 17 00:00:00 2001 From: Fraser Cormack Date: Wed, 26 May 2021 16:04:59 +0100 Subject: [PATCH] [DAGCombine][RISCV] Don't try to trunc-store combined vector stores DAGCombine's `mergeStoresOfConstantsOrVecElts` optimization is told whether it's to use vector types and also whether it's to issue a truncating store. However, the truncating store code path assumes a scalar integer `ConstantSDNode`, and when using vector types it creates either a `BUILD_VECTOR` or `CONCAT_VECTORS` to store: neither of which is a constant. The `riscv64` target is able to expose a crash here because it switches on both code paths at the same time. The `f32` is stored as `i32` which must be promoted to `i64`, necessitating a truncating store. It also decides later that it prefers a vector store of `v2f32`. While vector truncating stores are legal, this combine is not able to emit them. We also don't have a test case. This patch adds an assert to catch this case more gracefully, and updates one of the caller functions to the function to turn off the use of truncating stores when preferring vectors. Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D103173 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 12 +++++++++--- lib/Target/RISCV/RISCVISelLowering.cpp | 2 +- test/CodeGen/RISCV/rvv/combine-store-fp.ll | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/RISCV/rvv/combine-store-fp.ll diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 248e9d98410..0838e52a0ec 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -16726,6 +16726,9 @@ bool DAGCombiner::mergeStoresOfConstantsOrVecElts( if (NumStores < 2) return false; + assert((!UseTrunc || !UseVector) && + "This optimization cannot emit a vector truncating store"); + // The latest Node in the DAG. SDLoc DL(StoreNodes[0].MemNode); @@ -17221,6 +17224,7 @@ bool DAGCombiner::tryStoreMergeOfConstants( bool UseVector = (LastLegalVectorType > LastLegalType) && AllowVectors; unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType; + bool UseTrunc = LastIntegerTrunc && !UseVector; // Check if we found a legal integer type that creates a meaningful // merge. @@ -17251,8 +17255,9 @@ bool DAGCombiner::tryStoreMergeOfConstants( continue; } - MadeChange |= mergeStoresOfConstantsOrVecElts( - StoreNodes, MemVT, NumElem, true, UseVector, LastIntegerTrunc); + MadeChange |= mergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem, + /*IsConstantSrc*/ true, + UseVector, UseTrunc); // Remove merged stores for next iteration. StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumElem); @@ -17321,7 +17326,8 @@ bool DAGCombiner::tryStoreMergeOfExtracts( } MadeChange |= mergeStoresOfConstantsOrVecElts( - StoreNodes, MemVT, NumStoresToMerge, false, true, false); + StoreNodes, MemVT, NumStoresToMerge, /*IsConstantSrc*/ false, + /*UseVector*/ true, /*UseTrunc*/ false); StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumStoresToMerge); NumConsecutiveStores -= NumStoresToMerge; diff --git a/lib/Target/RISCV/RISCVISelLowering.cpp b/lib/Target/RISCV/RISCVISelLowering.cpp index 697c8eac9c3..0fba9a25ca2 100644 --- a/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/lib/Target/RISCV/RISCVISelLowering.cpp @@ -8429,7 +8429,7 @@ bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, bool RISCVTargetLowering::allowsMisalignedMemoryAccesses( EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, bool *Fast) const { - if (!VT.isScalableVector()) + if (!VT.isVector()) return false; EVT ElemVT = VT.getVectorElementType(); diff --git a/test/CodeGen/RISCV/rvv/combine-store-fp.ll b/test/CodeGen/RISCV/rvv/combine-store-fp.ll new file mode 100644 index 00000000000..8b045015e32 --- /dev/null +++ b/test/CodeGen/RISCV/rvv/combine-store-fp.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+d,+experimental-v -verify-machineinstrs -riscv-v-vector-bits-min=128 < %s | FileCheck %s +; RUN: llc -mtriple=riscv64 -mattr=+d,+experimental-v -verify-machineinstrs -riscv-v-vector-bits-min=128 < %s | FileCheck %s + +define void @combine_fp_zero_stores_crash(float* %ptr) { +; CHECK-LABEL: combine_fp_zero_stores_crash: +; CHECK: # %bb.0: +; CHECK-NEXT: addi a0, a0, 4 +; CHECK-NEXT: vsetivli zero, 2, e32,mf2,ta,mu +; CHECK-NEXT: vmv.v.i v25, 0 +; CHECK-NEXT: vse32.v v25, (a0) +; CHECK-NEXT: ret + %addr1 = getelementptr float, float * %ptr, i64 1 + %addr2 = getelementptr float, float * %ptr, i64 2 + store float 0.000000e+00, float * %addr1, align 4 + store float 0.000000e+00, float * %addr2, align 4 + ret void +}