Skip to content

[RISCV] Don't create BuildPairF64 or SplitF64 nodes without D or Zdinx. #116159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 14, 2024

Conversation

topperc
Copy link
Collaborator

@topperc topperc commented Nov 14, 2024

The fix in ReplaceNodeResults is the only one really required for the known crash.

I couldn't hit the case in LowerOperation because that requires (f64 (bitcast i64)), but the result type is softened before the input so we don't get a chance to legalize the input.

The change to the setOperationAction call was an observation that a i64<->vector cast should not be custom legalized on RV32. The custom code already calls isTypeLegal on the scalar type.

The fix in ReplaceNodeResults is the only one really required for
the known crash.

I couldn't hit the case in LowerOperation because that requires
(f64 (bitcast i64)), but the result type is softened before
the input so we don't get a chance to legalize the input.

The change to the setOperationAction call was an observation that
a i64<->vector cast should not be custom legalized on RV32. The
custom code already calls isTypeLegal on the scalar type.
@llvmbot
Copy link
Member

llvmbot commented Nov 14, 2024

@llvm/pr-subscribers-backend-risc-v

Author: Craig Topper (topperc)

Changes

The fix in ReplaceNodeResults is the only one really required for the known crash.

I couldn't hit the case in LowerOperation because that requires (f64 (bitcast i64)), but the result type is softened before the input so we don't get a chance to legalize the input.

The change to the setOperationAction call was an observation that a i64<->vector cast should not be custom legalized on RV32. The custom code already calls isTypeLegal on the scalar type.


Full diff: https://github.com/llvm/llvm-project/pull/116159.diff

2 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+7-3)
  • (added) llvm/test/CodeGen/RISCV/rvv/rv32-zve-bitcast-crash.ll (+24)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 3df8eca8cae7fb..706952925c1183 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1438,8 +1438,10 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
       }
 
       // Custom-legalize bitcasts from fixed-length vectors to scalar types.
-      setOperationAction(ISD::BITCAST, {MVT::i8, MVT::i16, MVT::i32, MVT::i64},
+      setOperationAction(ISD::BITCAST, {MVT::i8, MVT::i16, MVT::i32},
                          Custom);
+      if (Subtarget.is64Bit())
+        setOperationAction(ISD::BITCAST, MVT::i64, Custom);
       if (Subtarget.hasStdExtZfhminOrZhinxmin())
         setOperationAction(ISD::BITCAST, MVT::f16, Custom);
       if (Subtarget.hasStdExtZfbfmin())
@@ -6422,7 +6424,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
       SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op0);
       return DAG.getNode(RISCVISD::FMV_W_X_RV64, DL, MVT::f32, NewOp0);
     }
-    if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32) {
+    if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32 &&
+        Subtarget.hasStdExtDOrZdinx()) {
       SDValue Lo, Hi;
       std::tie(Lo, Hi) = DAG.SplitScalar(Op0, DL, MVT::i32, MVT::i32);
       return DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
@@ -12940,7 +12943,8 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
       SDValue FPConv =
           DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64, Op0);
       Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPConv));
-    } else if (VT == MVT::i64 && Op0VT == MVT::f64 && XLenVT == MVT::i32) {
+    } else if (VT == MVT::i64 && Op0VT == MVT::f64 && XLenVT == MVT::i32 &&
+               Subtarget.hasStdExtDOrZdinx()) {
       SDValue NewReg = DAG.getNode(RISCVISD::SplitF64, DL,
                                    DAG.getVTList(MVT::i32, MVT::i32), Op0);
       SDValue RetReg = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64,
diff --git a/llvm/test/CodeGen/RISCV/rvv/rv32-zve-bitcast-crash.ll b/llvm/test/CodeGen/RISCV/rvv/rv32-zve-bitcast-crash.ll
new file mode 100644
index 00000000000000..0749aab9b5e80d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/rv32-zve-bitcast-crash.ll
@@ -0,0 +1,24 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc < %s -mtriple=riscv32 -mattr=+zve32f,+zvl128b | FileCheck %s
+
+; This bitcast previously incorrectly produce a SplitF64 node.
+
+define i64 @foo(double %x) {
+; CHECK-LABEL: foo:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi sp, sp, -16
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; CHECK-NEXT:    .cfi_offset ra, -4
+; CHECK-NEXT:    lui a3, 261888
+; CHECK-NEXT:    li a2, 0
+; CHECK-NEXT:    call __adddf3
+; CHECK-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; CHECK-NEXT:    .cfi_restore ra
+; CHECK-NEXT:    addi sp, sp, 16
+; CHECK-NEXT:    .cfi_def_cfa_offset 0
+; CHECK-NEXT:    ret
+  %a = fadd double %x, 1.0
+  %b = bitcast double %a to i64
+  ret i64 %b
+}

Copy link

github-actions bot commented Nov 14, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Comment on lines 6426 to 6427
if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32 &&
Subtarget.hasStdExtDOrZdinx()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a readability suggestion:

Suggested change
if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32 &&
Subtarget.hasStdExtDOrZdinx()) {
if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
Subtarget.hasStdExtDOrZdinx()) {

Writing the conditions like this makes them match a lot more closely to the conditions on the relevant setOperationAction(ISD::BITCAST, MVT::i64, Custom); (on line 555 I believe)

I'll remove my similar change from the GPR Pairs PR, as it's no longer really relevant there.

@topperc topperc merged commit 0019565 into llvm:main Nov 14, 2024
6 of 7 checks passed
@topperc topperc deleted the pr/splitf64-rv32 branch November 14, 2024 17:54
@topperc topperc modified the milestone: LLVM 19.X Release Dec 27, 2024
topperc added a commit to topperc/llvm-project that referenced this pull request Jan 2, 2025
…x. (llvm#116159)

The fix in ReplaceNodeResults is the only one really required for the
known crash.

I couldn't hit the case in LowerOperation because that requires (f64
(bitcast i64)), but the result type is softened before the input so we
don't get a chance to legalize the input.

The change to the setOperationAction call was an observation that a
i64<->vector cast should not be custom legalized on RV32. The custom
code already calls isTypeLegal on the scalar type.
tru pushed a commit to topperc/llvm-project that referenced this pull request Jan 13, 2025
…x. (llvm#116159)

The fix in ReplaceNodeResults is the only one really required for the
known crash.

I couldn't hit the case in LowerOperation because that requires (f64
(bitcast i64)), but the result type is softened before the input so we
don't get a chance to legalize the input.

The change to the setOperationAction call was an observation that a
i64<->vector cast should not be custom legalized on RV32. The custom
code already calls isTypeLegal on the scalar type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Needs Triage
Development

Successfully merging this pull request may close these issues.

4 participants