Repository navigation
[RISCV] Consider truncate semantics in performBUILD_VECTORCombine - #81168
Merged
Merged
Conversation
Fixes llvm#80910. Per the documentation in ISDOpcodes.h, for BUILD_VECTOR "The types of the operands must match the vector element type, except that integer types are allowed to be larger than the element type, in which case the operands are implicitly truncated." This transform was assuming that the scalar operand type matched the result type. This resulted in essentially performing a truncate before a binop, instead of after. As demonstrated by the test case changes, this is often not legal.
Member
|
@llvm/pr-subscribers-backend-risc-v Author: Philip Reames (preames) ChangesFixes #80910. Per the documentation in ISDOpcodes.h, for BUILD_VECTOR "The types of the operands must match the vector element type, except that integer types are allowed to be larger than the element type, in which case the operands are implicitly truncated." This transform was assuming that the scalar operand type matched the result type. This resulted in essentially performing a truncate before a binop, instead of after. As demonstrated by the test case changes, this is often not legal. Patch is 27.15 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/81168.diff 4 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 27037f4d5c5c85..0799cc2e5901cb 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -14956,6 +14956,11 @@ static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG,
if (!TLI.isOperationLegalOrCustom(Opcode, VT) || !TLI.isTypeLegal(VT))
return SDValue();
+ // This BUILD_VECTOR involves an implicit truncation, and sinking
+ // truncates through binops is non-trivial.
+ if (N->op_begin()->getValueType() != VT.getVectorElementType())
+ return SDValue();
+
SmallVector<SDValue> LHSOps;
SmallVector<SDValue> RHSOps;
for (SDValue Op : N->ops()) {
@@ -14983,6 +14988,7 @@ static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG,
// have different LHS and RHS types.
if (Op.getOperand(0).getValueType() != Op.getOperand(1).getValueType())
return SDValue();
+
RHSOps.push_back(Op.getOperand(1));
}
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-buildvec-of-binop.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-buildvec-of-binop.ll
index e376688aca8a76..af7d7f7ae755bc 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-buildvec-of-binop.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-buildvec-of-binop.ll
@@ -589,7 +589,8 @@ define <8 x i32> @add_constant_rhs_8xi32_partial(<8 x i32> %vin, i32 %a, i32 %b,
ret <8 x i32> %v3
}
-; FIXME: This is currently showing a miscompile, we effectively
+; Here we can not pull the ashr through into the vector domain due to
+; the truncate semantics of the build_vector. Doing so would
; truncate before the ashr instead of after it, so if %a or %b
; is e.g. UINT32_MAX+1 we get different result.
define <2 x i32> @build_vec_of_trunc_op(i64 %a, i64 %b) {
@@ -608,10 +609,11 @@ define <2 x i32> @build_vec_of_trunc_op(i64 %a, i64 %b) {
;
; RV64-LABEL: build_vec_of_trunc_op:
; RV64: # %bb.0: # %entry
+; RV64-NEXT: srli a0, a0, 1
+; RV64-NEXT: srli a1, a1, 1
; RV64-NEXT: vsetivli zero, 2, e32, mf2, ta, ma
; RV64-NEXT: vmv.v.x v8, a0
; RV64-NEXT: vslide1down.vx v8, v8, a1
-; RV64-NEXT: vsrl.vi v8, v8, 1
; RV64-NEXT: ret
entry:
%conv11.i = ashr i64 %a, 1
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll
index cd47720e38216f..ead41b0717ff1c 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll
@@ -3,30 +3,65 @@
; RUN: llc -mtriple=riscv64 -target-abi=lp64d -mattr=+v,+zfh,+zvfh,+f,+d -verify-machineinstrs < %s | FileCheck %s -check-prefixes=CHECK,RV64
define void @vselect_vv_v6i32(ptr %a, ptr %b, ptr %cc, ptr %z) {
-; CHECK-LABEL: vselect_vv_v6i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: lbu a2, 0(a2)
-; CHECK-NEXT: vle32.v v8, (a1)
-; CHECK-NEXT: srli a1, a2, 1
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vmv.v.x v10, a2
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 2
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 3
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 4
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a2, a2, 5
-; CHECK-NEXT: vslide1down.vx v10, v10, a2
-; CHECK-NEXT: vslidedown.vi v10, v10, 2
-; CHECK-NEXT: vand.vi v10, v10, 1
-; CHECK-NEXT: vmsne.vi v0, v10, 0
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, tu, mu
-; CHECK-NEXT: vle32.v v8, (a0), v0.t
-; CHECK-NEXT: vse32.v v8, (a3)
-; CHECK-NEXT: ret
+; RV32-LABEL: vselect_vv_v6i32:
+; RV32: # %bb.0:
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: lbu a2, 0(a2)
+; RV32-NEXT: vle32.v v8, (a1)
+; RV32-NEXT: slli a1, a2, 30
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: andi a4, a2, 1
+; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV32-NEXT: vmv.v.x v10, a4
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 29
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 28
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 27
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: srli a2, a2, 5
+; RV32-NEXT: vslide1down.vx v10, v10, a2
+; RV32-NEXT: vslidedown.vi v10, v10, 2
+; RV32-NEXT: vand.vi v10, v10, 1
+; RV32-NEXT: vmsne.vi v0, v10, 0
+; RV32-NEXT: vsetivli zero, 6, e32, m2, tu, mu
+; RV32-NEXT: vle32.v v8, (a0), v0.t
+; RV32-NEXT: vse32.v v8, (a3)
+; RV32-NEXT: ret
+;
+; RV64-LABEL: vselect_vv_v6i32:
+; RV64: # %bb.0:
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: lbu a2, 0(a2)
+; RV64-NEXT: vle32.v v8, (a1)
+; RV64-NEXT: slli a1, a2, 62
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: andi a4, a2, 1
+; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV64-NEXT: vmv.v.x v10, a4
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 61
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 60
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 59
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: srli a2, a2, 5
+; RV64-NEXT: vslide1down.vx v10, v10, a2
+; RV64-NEXT: vslidedown.vi v10, v10, 2
+; RV64-NEXT: vand.vi v10, v10, 1
+; RV64-NEXT: vmsne.vi v0, v10, 0
+; RV64-NEXT: vsetivli zero, 6, e32, m2, tu, mu
+; RV64-NEXT: vle32.v v8, (a0), v0.t
+; RV64-NEXT: vse32.v v8, (a3)
+; RV64-NEXT: ret
%va = load <6 x i32>, ptr %a
%vb = load <6 x i32>, ptr %b
%vcc = load <6 x i1>, ptr %cc
@@ -36,31 +71,67 @@ define void @vselect_vv_v6i32(ptr %a, ptr %b, ptr %cc, ptr %z) {
}
define void @vselect_vx_v6i32(i32 %a, ptr %b, ptr %cc, ptr %z) {
-; CHECK-LABEL: vselect_vx_v6i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: lbu a2, 0(a2)
-; CHECK-NEXT: vle32.v v8, (a1)
-; CHECK-NEXT: srli a1, a2, 1
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vmv.v.x v10, a2
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 2
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 3
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 4
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a2, a2, 5
-; CHECK-NEXT: vslide1down.vx v10, v10, a2
-; CHECK-NEXT: vslidedown.vi v10, v10, 2
-; CHECK-NEXT: vand.vi v10, v10, 1
-; CHECK-NEXT: vmsne.vi v0, v10, 0
-; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma
-; CHECK-NEXT: vmerge.vxm v8, v8, a0, v0
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: vse32.v v8, (a3)
-; CHECK-NEXT: ret
+; RV32-LABEL: vselect_vx_v6i32:
+; RV32: # %bb.0:
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: lbu a2, 0(a2)
+; RV32-NEXT: vle32.v v8, (a1)
+; RV32-NEXT: slli a1, a2, 30
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: andi a4, a2, 1
+; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV32-NEXT: vmv.v.x v10, a4
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 29
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 28
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 27
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: srli a2, a2, 5
+; RV32-NEXT: vslide1down.vx v10, v10, a2
+; RV32-NEXT: vslidedown.vi v10, v10, 2
+; RV32-NEXT: vand.vi v10, v10, 1
+; RV32-NEXT: vmsne.vi v0, v10, 0
+; RV32-NEXT: vsetvli zero, zero, e32, m2, ta, ma
+; RV32-NEXT: vmerge.vxm v8, v8, a0, v0
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: vse32.v v8, (a3)
+; RV32-NEXT: ret
+;
+; RV64-LABEL: vselect_vx_v6i32:
+; RV64: # %bb.0:
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: lbu a2, 0(a2)
+; RV64-NEXT: vle32.v v8, (a1)
+; RV64-NEXT: slli a1, a2, 62
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: andi a4, a2, 1
+; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV64-NEXT: vmv.v.x v10, a4
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 61
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 60
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 59
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: srli a2, a2, 5
+; RV64-NEXT: vslide1down.vx v10, v10, a2
+; RV64-NEXT: vslidedown.vi v10, v10, 2
+; RV64-NEXT: vand.vi v10, v10, 1
+; RV64-NEXT: vmsne.vi v0, v10, 0
+; RV64-NEXT: vsetvli zero, zero, e32, m2, ta, ma
+; RV64-NEXT: vmerge.vxm v8, v8, a0, v0
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: vse32.v v8, (a3)
+; RV64-NEXT: ret
%vb = load <6 x i32>, ptr %b
%ahead = insertelement <6 x i32> poison, i32 %a, i32 0
%va = shufflevector <6 x i32> %ahead, <6 x i32> poison, <6 x i32> zeroinitializer
@@ -71,31 +142,67 @@ define void @vselect_vx_v6i32(i32 %a, ptr %b, ptr %cc, ptr %z) {
}
define void @vselect_vi_v6i32(ptr %b, ptr %cc, ptr %z) {
-; CHECK-LABEL: vselect_vi_v6i32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: lbu a1, 0(a1)
-; CHECK-NEXT: vle32.v v8, (a0)
-; CHECK-NEXT: srli a0, a1, 1
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vmv.v.x v10, a1
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a0, a1, 2
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a0, a1, 3
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a0, a1, 4
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a1, a1, 5
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: vslidedown.vi v10, v10, 2
-; CHECK-NEXT: vand.vi v10, v10, 1
-; CHECK-NEXT: vmsne.vi v0, v10, 0
-; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma
-; CHECK-NEXT: vmerge.vim v8, v8, -1, v0
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: vse32.v v8, (a2)
-; CHECK-NEXT: ret
+; RV32-LABEL: vselect_vi_v6i32:
+; RV32: # %bb.0:
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: lbu a1, 0(a1)
+; RV32-NEXT: vle32.v v8, (a0)
+; RV32-NEXT: slli a0, a1, 30
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: andi a3, a1, 1
+; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV32-NEXT: vmv.v.x v10, a3
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: slli a0, a1, 29
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: slli a0, a1, 28
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: slli a0, a1, 27
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: srli a1, a1, 5
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: vslidedown.vi v10, v10, 2
+; RV32-NEXT: vand.vi v10, v10, 1
+; RV32-NEXT: vmsne.vi v0, v10, 0
+; RV32-NEXT: vsetvli zero, zero, e32, m2, ta, ma
+; RV32-NEXT: vmerge.vim v8, v8, -1, v0
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: vse32.v v8, (a2)
+; RV32-NEXT: ret
+;
+; RV64-LABEL: vselect_vi_v6i32:
+; RV64: # %bb.0:
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: lbu a1, 0(a1)
+; RV64-NEXT: vle32.v v8, (a0)
+; RV64-NEXT: slli a0, a1, 62
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: andi a3, a1, 1
+; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV64-NEXT: vmv.v.x v10, a3
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: slli a0, a1, 61
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: slli a0, a1, 60
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: slli a0, a1, 59
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: srli a1, a1, 5
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: vslidedown.vi v10, v10, 2
+; RV64-NEXT: vand.vi v10, v10, 1
+; RV64-NEXT: vmsne.vi v0, v10, 0
+; RV64-NEXT: vsetvli zero, zero, e32, m2, ta, ma
+; RV64-NEXT: vmerge.vim v8, v8, -1, v0
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: vse32.v v8, (a2)
+; RV64-NEXT: ret
%vb = load <6 x i32>, ptr %b
%a = insertelement <6 x i32> poison, i32 -1, i32 0
%va = shufflevector <6 x i32> %a, <6 x i32> poison, <6 x i32> zeroinitializer
@@ -107,30 +214,65 @@ define void @vselect_vi_v6i32(ptr %b, ptr %cc, ptr %z) {
define void @vselect_vv_v6f32(ptr %a, ptr %b, ptr %cc, ptr %z) {
-; CHECK-LABEL: vselect_vv_v6f32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: lbu a2, 0(a2)
-; CHECK-NEXT: vle32.v v8, (a1)
-; CHECK-NEXT: srli a1, a2, 1
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vmv.v.x v10, a2
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 2
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 3
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a1, a2, 4
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: srli a2, a2, 5
-; CHECK-NEXT: vslide1down.vx v10, v10, a2
-; CHECK-NEXT: vslidedown.vi v10, v10, 2
-; CHECK-NEXT: vand.vi v10, v10, 1
-; CHECK-NEXT: vmsne.vi v0, v10, 0
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, tu, mu
-; CHECK-NEXT: vle32.v v8, (a0), v0.t
-; CHECK-NEXT: vse32.v v8, (a3)
-; CHECK-NEXT: ret
+; RV32-LABEL: vselect_vv_v6f32:
+; RV32: # %bb.0:
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: lbu a2, 0(a2)
+; RV32-NEXT: vle32.v v8, (a1)
+; RV32-NEXT: slli a1, a2, 30
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: andi a4, a2, 1
+; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV32-NEXT: vmv.v.x v10, a4
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 29
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 28
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: slli a1, a2, 27
+; RV32-NEXT: srli a1, a1, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: srli a2, a2, 5
+; RV32-NEXT: vslide1down.vx v10, v10, a2
+; RV32-NEXT: vslidedown.vi v10, v10, 2
+; RV32-NEXT: vand.vi v10, v10, 1
+; RV32-NEXT: vmsne.vi v0, v10, 0
+; RV32-NEXT: vsetivli zero, 6, e32, m2, tu, mu
+; RV32-NEXT: vle32.v v8, (a0), v0.t
+; RV32-NEXT: vse32.v v8, (a3)
+; RV32-NEXT: ret
+;
+; RV64-LABEL: vselect_vv_v6f32:
+; RV64: # %bb.0:
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: lbu a2, 0(a2)
+; RV64-NEXT: vle32.v v8, (a1)
+; RV64-NEXT: slli a1, a2, 62
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: andi a4, a2, 1
+; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV64-NEXT: vmv.v.x v10, a4
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 61
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 60
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: slli a1, a2, 59
+; RV64-NEXT: srli a1, a1, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: srli a2, a2, 5
+; RV64-NEXT: vslide1down.vx v10, v10, a2
+; RV64-NEXT: vslidedown.vi v10, v10, 2
+; RV64-NEXT: vand.vi v10, v10, 1
+; RV64-NEXT: vmsne.vi v0, v10, 0
+; RV64-NEXT: vsetivli zero, 6, e32, m2, tu, mu
+; RV64-NEXT: vle32.v v8, (a0), v0.t
+; RV64-NEXT: vse32.v v8, (a3)
+; RV64-NEXT: ret
%va = load <6 x float>, ptr %a
%vb = load <6 x float>, ptr %b
%vcc = load <6 x i1>, ptr %cc
@@ -140,31 +282,67 @@ define void @vselect_vv_v6f32(ptr %a, ptr %b, ptr %cc, ptr %z) {
}
define void @vselect_vx_v6f32(float %a, ptr %b, ptr %cc, ptr %z) {
-; CHECK-LABEL: vselect_vx_v6f32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: lbu a1, 0(a1)
-; CHECK-NEXT: vle32.v v8, (a0)
-; CHECK-NEXT: srli a0, a1, 1
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vmv.v.x v10, a1
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a0, a1, 2
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a0, a1, 3
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a0, a1, 4
-; CHECK-NEXT: vslide1down.vx v10, v10, a0
-; CHECK-NEXT: srli a1, a1, 5
-; CHECK-NEXT: vslide1down.vx v10, v10, a1
-; CHECK-NEXT: vslidedown.vi v10, v10, 2
-; CHECK-NEXT: vand.vi v10, v10, 1
-; CHECK-NEXT: vmsne.vi v0, v10, 0
-; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma
-; CHECK-NEXT: vfmerge.vfm v8, v8, fa0, v0
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: vse32.v v8, (a2)
-; CHECK-NEXT: ret
+; RV32-LABEL: vselect_vx_v6f32:
+; RV32: # %bb.0:
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: lbu a1, 0(a1)
+; RV32-NEXT: vle32.v v8, (a0)
+; RV32-NEXT: slli a0, a1, 30
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: andi a3, a1, 1
+; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV32-NEXT: vmv.v.x v10, a3
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: slli a0, a1, 29
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: slli a0, a1, 28
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: slli a0, a1, 27
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: vslide1down.vx v10, v10, a0
+; RV32-NEXT: srli a1, a1, 5
+; RV32-NEXT: vslide1down.vx v10, v10, a1
+; RV32-NEXT: vslidedown.vi v10, v10, 2
+; RV32-NEXT: vand.vi v10, v10, 1
+; RV32-NEXT: vmsne.vi v0, v10, 0
+; RV32-NEXT: vsetvli zero, zero, e32, m2, ta, ma
+; RV32-NEXT: vfmerge.vfm v8, v8, fa0, v0
+; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV32-NEXT: vse32.v v8, (a2)
+; RV32-NEXT: ret
+;
+; RV64-LABEL: vselect_vx_v6f32:
+; RV64: # %bb.0:
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: lbu a1, 0(a1)
+; RV64-NEXT: vle32.v v8, (a0)
+; RV64-NEXT: slli a0, a1, 62
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: andi a3, a1, 1
+; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
+; RV64-NEXT: vmv.v.x v10, a3
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: slli a0, a1, 61
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: slli a0, a1, 60
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: slli a0, a1, 59
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: vslide1down.vx v10, v10, a0
+; RV64-NEXT: srli a1, a1, 5
+; RV64-NEXT: vslide1down.vx v10, v10, a1
+; RV64-NEXT: vslidedown.vi v10, v10, 2
+; RV64-NEXT: vand.vi v10, v10, 1
+; RV64-NEXT: vmsne.vi v0, v10, 0
+; RV64-NEXT: vsetvli zero, zero, e32, m2, ta, ma
+; RV64-NEXT: vfmerge.vfm v8, v8, fa0, v0
+; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, ma
+; RV64-NEXT: vse32.v v8, (a2)
+; RV64-NEXT: ret
%vb = load <6 x float>, ptr %b
%ahead = insertelement <6 x float> poison, float %a, i32 0
%va = shufflevector <6 x float> %ahead, <6 x float> poison, <6 x i32> zeroinitializer
@@ -175,31 +353,67 @@ define void @vselect_vx_v6f32(float %a, ptr %b, ptr %cc, ptr %z) {
}
define void @vselect_vfpzero_v6f32(ptr %b, ptr %cc, ptr %z) {
-; CHECK-LABEL: vselect_vfpzero_v6f32:
-; CHECK: # %bb.0:
-; CHECK-NEXT: vsetivli zero, 6, e32, m2, ta, ma
-; CHECK-NEXT: lbu a1, 0(a1)
-; CHECK-NEXT: vle32.v v8, (a0)
-; CHECK-NEXT: srli a0, a1, 1
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; ...
[truncated]
|
asb
added a commit
that referenced
this pull request
Oct 2, 2026
#228243) This fixes a miscompile in performINSERT_VECTOR_ELTCombine dating back to when it was added (#72675), but only just showing up through testing when a recent unrelated change triggered vectorisation for a function that trips it within Clang, leading to broken builds on some of the two-stage RVV buildbots. After type legalization the scalar binop can be wider than the vector element type, with the insert implicitly truncating it. That isn't equivalent for shifts and a similar bug was found and fixed in a neighbouring combine in #81168. This patch just applies the same fix (with the same comment even), avoiding the transform if the scalar type doesn't match the element type. I used an LLM to root cause the issue and produce the test case.
Expertcoderz
pushed a commit
to Expertcoderz/llvm-project
that referenced
this pull request
Oct 3, 2026
llvm#228243) This fixes a miscompile in performINSERT_VECTOR_ELTCombine dating back to when it was added (llvm#72675), but only just showing up through testing when a recent unrelated change triggered vectorisation for a function that trips it within Clang, leading to broken builds on some of the two-stage RVV buildbots. After type legalization the scalar binop can be wider than the vector element type, with the insert implicitly truncating it. That isn't equivalent for shifts and a similar bug was found and fixed in a neighbouring combine in llvm#81168. This patch just applies the same fix (with the same comment even), avoiding the transform if the scalar type doesn't match the element type. I used an LLM to root cause the issue and produce the test case.
tru
pushed a commit
that referenced
this pull request
Oct 5, 2026
#228243) This fixes a miscompile in performINSERT_VECTOR_ELTCombine dating back to when it was added (#72675), but only just showing up through testing when a recent unrelated change triggered vectorisation for a function that trips it within Clang, leading to broken builds on some of the two-stage RVV buildbots. After type legalization the scalar binop can be wider than the vector element type, with the insert implicitly truncating it. That isn't equivalent for shifts and a similar bug was found and fixed in a neighbouring combine in #81168. This patch just applies the same fix (with the same comment even), avoiding the transform if the scalar type doesn't match the element type. I used an LLM to root cause the issue and produce the test case. (cherry picked from commit 58d59f4)
paleauraaaa
pushed a commit
to paleauraaaa/llvm-project
that referenced
this pull request
Oct 7, 2026
…vm#81168) Fixes llvm#80910. Per the documentation in ISDOpcodes.h, for BUILD_VECTOR "The types of the operands must match the vector element type, except that integer types are allowed to be larger than the element type, in which case the operands are implicitly truncated." This transform was assuming that the scalar operand type matched the result type. This resulted in essentially performing a truncate before a binop, instead of after. As demonstrated by the test case changes, this is often not legal.
gandhi56
pushed a commit
that referenced
this pull request
Oct 7, 2026
#228243) This fixes a miscompile in performINSERT_VECTOR_ELTCombine dating back to when it was added (#72675), but only just showing up through testing when a recent unrelated change triggered vectorisation for a function that trips it within Clang, leading to broken builds on some of the two-stage RVV buildbots. After type legalization the scalar binop can be wider than the vector element type, with the insert implicitly truncating it. That isn't equivalent for shifts and a similar bug was found and fixed in a neighbouring combine in #81168. This patch just applies the same fix (with the same comment even), avoiding the transform if the scalar type doesn't match the element type. I used an LLM to root cause the issue and produce the test case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #80910.
Per the documentation in ISDOpcodes.h, for BUILD_VECTOR "The types of the operands must match the vector element type, except that integer types are allowed to be larger than the element type, in which case the operands are implicitly truncated."
This transform was assuming that the scalar operand type matched the result type. This resulted in essentially performing a truncate before a binop, instead of after. As demonstrated by the test case changes, this is often not legal.