diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -20538,6 +20538,26 @@ if (SDValue BO = scalarizeExtractedBinop(N, DAG, LegalOperations)) return BO; + // extract_vector_elt (bitcast (splat_vector x)), n -> y + if (IndexC && ScalarVT.isInteger() && VecOp.getOpcode() == ISD::BITCAST && + VecOp.getOperand(0).getOpcode() == ISD::SPLAT_VECTOR) { + SDNode *Splat = VecOp.getOperand(0).getNode(); + SDValue SplatVal = Splat->getOperand(0); + if (SplatVal.isUndef()) + return DAG.getUNDEF(ScalarVT); + + if (auto *CInt = dyn_cast(SplatVal.getNode())) { + APInt Val = APInt::getSplat( + Splat->getValueType(0).getSizeInBits().getKnownMinSize(), + CInt->getAPIntValue()); + + APInt BitcastExtEl = Val.extractBits(ScalarVT.getFixedSizeInBits(), + IndexC->getZExtValue() * + ScalarVT.getFixedSizeInBits()); + return DAG.getConstant(BitcastExtEl, DL, ScalarVT); + } + } + if (VecVT.isScalableVector()) return SDValue(); diff --git a/llvm/test/CodeGen/RISCV/vector-extract-elt-bitcast-splat.ll b/llvm/test/CodeGen/RISCV/vector-extract-elt-bitcast-splat.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/vector-extract-elt-bitcast-splat.ll @@ -0,0 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+v < %s | FileCheck %s + +; This ensures that a bitcast of a splat_vector can be still be constant folded +; from extract_vector_elt + +define i32 @f( %a) { +; CHECK-LABEL: f: +; CHECK: # %bb.0: +; CHECK-NEXT: li a0, 0 +; CHECK-NEXT: ret + %v = insertelement %a, i64 0, i32 0 + %w = shufflevector %v, undef, zeroinitializer + %x = bitcast %w to + %y = extractelement %x, i32 0 + ret i32 %y +} diff --git a/llvm/test/CodeGen/WebAssembly/pr59626.ll b/llvm/test/CodeGen/WebAssembly/pr59626.ll --- a/llvm/test/CodeGen/WebAssembly/pr59626.ll +++ b/llvm/test/CodeGen/WebAssembly/pr59626.ll @@ -12,12 +12,7 @@ ; CHECK-32-NEXT: local.get 0 ; CHECK-32-NEXT: i32.const 0 ; CHECK-32-NEXT: i32.store16 0 -; CHECK-32-NEXT: local.get 1 -; CHECK-32-NEXT: local.get 0 -; CHECK-32-NEXT: i8x16.splat -; CHECK-32-NEXT: v128.store16_lane 0, 0 -; CHECK-32-NEXT: v128.const 0, 0 -; CHECK-32-NEXT: i32x4.extract_lane 0 +; CHECK-32-NEXT: i32.const 0 ; CHECK-32-NEXT: # fallthrough-return ; ; CHECK-64-LABEL: f: @@ -35,8 +30,7 @@ ; CHECK-64-NEXT: i8x16.splat ; CHECK-64-NEXT: v128.store16_lane 0, 0 ; CHECK-64-NEXT: drop -; CHECK-64-NEXT: v128.const 0, 0 -; CHECK-64-NEXT: i32x4.extract_lane 0 +; CHECK-64-NEXT: i32.const 0 ; CHECK-64-NEXT: # fallthrough-return BB: store <3 x i8> zeroinitializer, ptr %0