[llvm] [SystemZ] Fix assertion failures during DAG combine (PR #215027)
Jacob Young via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 8 14:05:59 PDT 2026
https://github.com/jacobly0 created https://github.com/llvm/llvm-project/pull/215027
Previously this code would generate:
i16 = bitcast f16
i32 = truncate i16
Which would immediately assert due to the invalid truncate, but even with that fixed it would assert later due to the illegal i16. Instead, use the same lowering as `LowerOperationWrapper` for the bitcast.
>From ff128775014ef36576e89855ab6322680fc1d56e Mon Sep 17 00:00:00 2001
From: Jacob Young <jacobly at ziglang.org>
Date: Sat, 8 Aug 2026 16:49:16 -0400
Subject: [PATCH] [SystemZ] Fix assertion failures during DAG combine
Previously this code would generate:
i16 = bitcast f16
i32 = truncate i16
Which would immediately assert due to the invalid truncate, but even
with that fixed it would assert later due to the illegal i16. Instead,
use the same lowering as `LowerOperationWrapper` for the bitcast.
---
.../Target/SystemZ/SystemZISelLowering.cpp | 10 +-
.../CodeGen/SystemZ/fp-half-vector-abs.ll | 124 ++++++++++++++++++
2 files changed, 132 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/SystemZ/fp-half-vector-abs.ll
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 710832525426b..1a72683b53f42 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -7632,8 +7632,14 @@ SDValue SystemZTargetLowering::combineExtract(const SDLoc &DL, EVT ResVT,
// We're extracting the low part of one operand of the BUILD_VECTOR.
Op = Op.getOperand(End / OpBytesPerElement - 1);
if (!Op.getValueType().isInteger()) {
- EVT VT = MVT::getIntegerVT(Op.getValueSizeInBits());
- Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
+ if (Op.getValueType() == MVT::f16) {
+ assert(Subtarget.hasVector() && "canTreatAsByteVector was true");
+ Op = SDValue(DAG.getMachineNode(SystemZ::LFER_16, DL, MVT::i32, Op),
+ 0);
+ } else {
+ EVT VT = MVT::getIntegerVT(Op.getValueSizeInBits());
+ Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
+ }
DCI.AddToWorklist(Op.getNode());
}
EVT VT = MVT::getIntegerVT(ResVT.getSizeInBits());
diff --git a/llvm/test/CodeGen/SystemZ/fp-half-vector-abs.ll b/llvm/test/CodeGen/SystemZ/fp-half-vector-abs.ll
new file mode 100644
index 0000000000000..7663518f1e122
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/fp-half-vector-abs.ll
@@ -0,0 +1,124 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z16 | FileCheck %s --check-prefix=VECTOR
+
+define <2 x half> @fabs_f16(<2 x half> %arg) {
+; CHECK-LABEL: fabs_f16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: stmg %r12, %r15, 96(%r15)
+; CHECK-NEXT: .cfi_offset %r12, -64
+; CHECK-NEXT: .cfi_offset %r13, -56
+; CHECK-NEXT: .cfi_offset %r14, -48
+; CHECK-NEXT: .cfi_offset %r15, -40
+; CHECK-NEXT: aghi %r15, -184
+; CHECK-NEXT: .cfi_def_cfa_offset 344
+; CHECK-NEXT: std %f8, 176(%r15) # 8-byte Spill
+; CHECK-NEXT: std %f9, 168(%r15) # 8-byte Spill
+; CHECK-NEXT: std %f10, 160(%r15) # 8-byte Spill
+; CHECK-NEXT: .cfi_offset %f8, -168
+; CHECK-NEXT: .cfi_offset %f9, -176
+; CHECK-NEXT: .cfi_offset %f10, -184
+; CHECK-NEXT: ler %f8, %f2
+; CHECK-NEXT: ler %f10, %f0
+; CHECK-NEXT: lgdr %r0, %f8
+; CHECK-NEXT: srlg %r0, %r0, 48
+; CHECK-NEXT: lhr %r13, %r0
+; CHECK-NEXT: lgdr %r0, %f10
+; CHECK-NEXT: srlg %r0, %r0, 48
+; CHECK-NEXT: lcdfr %f0, %f0
+; CHECK-NEXT: lhr %r12, %r0
+; CHECK-NEXT: brasl %r14, __extendhfsf2 at PLT
+; CHECK-NEXT: ler %f9, %f0
+; CHECK-NEXT: ler %f0, %f10
+; CHECK-NEXT: brasl %r14, __extendhfsf2 at PLT
+; CHECK-NEXT: lcdfr %f10, %f8
+; CHECK-NEXT: cijl %r12, 0, .LBB0_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: ler %f9, %f0
+; CHECK-NEXT: .LBB0_2:
+; CHECK-NEXT: ler %f0, %f9
+; CHECK-NEXT: brasl %r14, __truncsfhf2 at PLT
+; CHECK-NEXT: ler %f9, %f0
+; CHECK-NEXT: ler %f0, %f10
+; CHECK-NEXT: brasl %r14, __extendhfsf2 at PLT
+; CHECK-NEXT: ler %f10, %f0
+; CHECK-NEXT: ler %f0, %f8
+; CHECK-NEXT: brasl %r14, __extendhfsf2 at PLT
+; CHECK-NEXT: cijl %r13, 0, .LBB0_4
+; CHECK-NEXT: # %bb.3:
+; CHECK-NEXT: ler %f10, %f0
+; CHECK-NEXT: .LBB0_4:
+; CHECK-NEXT: ler %f0, %f10
+; CHECK-NEXT: brasl %r14, __truncsfhf2 at PLT
+; CHECK-NEXT: ler %f2, %f0
+; CHECK-NEXT: ler %f0, %f9
+; CHECK-NEXT: ld %f8, 176(%r15) # 8-byte Reload
+; CHECK-NEXT: ld %f9, 168(%r15) # 8-byte Reload
+; CHECK-NEXT: ld %f10, 160(%r15) # 8-byte Reload
+; CHECK-NEXT: lmg %r12, %r15, 280(%r15)
+; CHECK-NEXT: br %r14
+;
+; VECTOR-LABEL: fabs_f16:
+; VECTOR: # %bb.0:
+; VECTOR-NEXT: stmg %r12, %r15, 96(%r15)
+; VECTOR-NEXT: .cfi_offset %r12, -64
+; VECTOR-NEXT: .cfi_offset %r13, -56
+; VECTOR-NEXT: .cfi_offset %r14, -48
+; VECTOR-NEXT: .cfi_offset %r15, -40
+; VECTOR-NEXT: aghi %r15, -208
+; VECTOR-NEXT: .cfi_def_cfa_offset 368
+; VECTOR-NEXT: std %f8, 200(%r15) # 8-byte Spill
+; VECTOR-NEXT: std %f9, 192(%r15) # 8-byte Spill
+; VECTOR-NEXT: .cfi_offset %f8, -168
+; VECTOR-NEXT: .cfi_offset %f9, -176
+; VECTOR-NEXT: vlr %v0, %v24
+; VECTOR-NEXT: vlgvh %r0, %v0, 0
+; VECTOR-NEXT: vreph %v1, %v24, 1
+; VECTOR-NEXT: lhr %r13, %r0
+; VECTOR-NEXT: vlgvh %r0, %v1, 0
+; VECTOR-NEXT: lcdfr %f0, %f1
+; VECTOR-NEXT: vst %v24, 176(%r15), 3 # 16-byte Spill
+; VECTOR-NEXT: vst %v1, 160(%r15), 3 # 16-byte Spill
+; VECTOR-NEXT: lhr %r12, %r0
+; VECTOR-NEXT: brasl %r14, __extendhfsf2 at PLT
+; VECTOR-NEXT: ldr %f8, %f0
+; VECTOR-NEXT: vl %v0, 160(%r15), 3 # 16-byte Reload
+; VECTOR-NEXT: # kill: def $f0h killed $f0h killed $v0
+; VECTOR-NEXT: brasl %r14, __extendhfsf2 at PLT
+; VECTOR-NEXT: vl %v1, 176(%r15), 3 # 16-byte Reload
+; VECTOR-NEXT: lcdfr %f9, %f1
+; VECTOR-NEXT: cijl %r12, 0, .LBB0_2
+; VECTOR-NEXT: # %bb.1:
+; VECTOR-NEXT: ldr %f8, %f0
+; VECTOR-NEXT: .LBB0_2:
+; VECTOR-NEXT: ldr %f0, %f8
+; VECTOR-NEXT: brasl %r14, __truncsfhf2 at PLT
+; VECTOR-NEXT: # kill: def $f0h killed $f0h def $v0
+; VECTOR-NEXT: vst %v0, 160(%r15), 3 # 16-byte Spill
+; VECTOR-NEXT: ldr %f0, %f9
+; VECTOR-NEXT: brasl %r14, __extendhfsf2 at PLT
+; VECTOR-NEXT: ldr %f8, %f0
+; VECTOR-NEXT: vl %v0, 176(%r15), 3 # 16-byte Reload
+; VECTOR-NEXT: # kill: def $f0h killed $f0h killed $v0
+; VECTOR-NEXT: brasl %r14, __extendhfsf2 at PLT
+; VECTOR-NEXT: cijl %r13, 0, .LBB0_4
+; VECTOR-NEXT: # %bb.3:
+; VECTOR-NEXT: ldr %f8, %f0
+; VECTOR-NEXT: .LBB0_4:
+; VECTOR-NEXT: ldr %f0, %f8
+; VECTOR-NEXT: brasl %r14, __truncsfhf2 at PLT
+; VECTOR-NEXT: vl %v1, 160(%r15), 3 # 16-byte Reload
+; VECTOR-NEXT: # kill: def $f0h killed $f0h def $v0
+; VECTOR-NEXT: vmrhh %v0, %v0, %v1
+; VECTOR-NEXT: ld %f8, 200(%r15) # 8-byte Reload
+; VECTOR-NEXT: ld %f9, 192(%r15) # 8-byte Reload
+; VECTOR-NEXT: vmrhf %v0, %v0, %v0
+; VECTOR-NEXT: vmrhg %v24, %v0, %v0
+; VECTOR-NEXT: lmg %r12, %r15, 304(%r15)
+; VECTOR-NEXT: br %r14
+ %bits = bitcast <2 x half> %arg to <2 x i16>
+ %is_neg = icmp slt <2 x i16> %bits, zeroinitializer
+ %neg = fneg <2 x half> %arg
+ %res = select <2 x i1> %is_neg, <2 x half> %neg, <2 x half> %arg
+ ret <2 x half> %res
+}
More information about the llvm-commits
mailing list