-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[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
Conversation
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.
@llvm/pr-subscribers-backend-risc-v Author: Craig Topper (topperc) ChangesThe 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:
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
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32 && | ||
Subtarget.hasStdExtDOrZdinx()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a readability suggestion:
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.
…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.
…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.
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.