[RISCV] Implement RISCVTargetLowering::getRoundingControlRegisters (#139864)
By adding FRM/FFLAGS as implicit defs, ReadFRM is not optimized out.
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 8c9ca63..1158499 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -24509,3 +24509,11 @@
MF.getInfo<RISCVMachineFunctionInfo>()->setDynamicAllocation();
return ExitMBB->begin()->getParent();
}
+
+ArrayRef<MCPhysReg> RISCVTargetLowering::getRoundingControlRegisters() const {
+ if (Subtarget.hasStdExtFOrZfinx()) {
+ static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
+ return RCRegs;
+ }
+ return {};
+}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index c865da8..fc8d8b8 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -450,6 +450,8 @@
MachineBasicBlock *emitDynamicProbedAlloc(MachineInstr &MI,
MachineBasicBlock *MBB) const;
+ ArrayRef<MCPhysReg> getRoundingControlRegisters() const override;
+
private:
void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
diff --git a/llvm/test/CodeGen/RISCV/fpenv.ll b/llvm/test/CodeGen/RISCV/fpenv.ll
index d9da14b..11e104a 100644
--- a/llvm/test/CodeGen/RISCV/fpenv.ll
+++ b/llvm/test/CodeGen/RISCV/fpenv.ll
@@ -40,16 +40,22 @@
; RV32IF-NEXT: frrm a0
; RV32IF-NEXT: lui a1, 66
; RV32IF-NEXT: slli a0, a0, 2
-; RV32IF-NEXT: addi a1, a1, 769
-; RV32IF-NEXT: srl s0, a1, a0
+; RV32IF-NEXT: addi s0, a1, 769
+; RV32IF-NEXT: srl a0, s0, a0
+; RV32IF-NEXT: andi a0, a0, 7
+; RV32IF-NEXT: beqz a0, .LBB1_2
+; RV32IF-NEXT: # %bb.1:
; RV32IF-NEXT: li a0, 0
-; RV32IF-NEXT: andi s0, s0, 7
-; RV32IF-NEXT: bnez s0, .LBB1_2
-; RV32IF-NEXT: # %bb.1: # %if.end
+; RV32IF-NEXT: j .LBB1_3
+; RV32IF-NEXT: .LBB1_2: # %if.end
; RV32IF-NEXT: call fesetround
-; RV32IF-NEXT: addi s0, s0, -1
-; RV32IF-NEXT: seqz a0, s0
-; RV32IF-NEXT: .LBB1_2: # %return
+; RV32IF-NEXT: frrm a0
+; RV32IF-NEXT: slli a0, a0, 2
+; RV32IF-NEXT: srl a0, s0, a0
+; RV32IF-NEXT: andi a0, a0, 7
+; RV32IF-NEXT: addi a0, a0, -1
+; RV32IF-NEXT: seqz a0, a0
+; RV32IF-NEXT: .LBB1_3: # %return
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32IF-NEXT: .cfi_restore ra
@@ -71,16 +77,22 @@
; RV64IF-NEXT: frrm a0
; RV64IF-NEXT: lui a1, 66
; RV64IF-NEXT: slli a0, a0, 2
-; RV64IF-NEXT: addiw a1, a1, 769
-; RV64IF-NEXT: srl s0, a1, a0
+; RV64IF-NEXT: addiw s0, a1, 769
+; RV64IF-NEXT: srl a0, s0, a0
+; RV64IF-NEXT: andi a0, a0, 7
+; RV64IF-NEXT: beqz a0, .LBB1_2
+; RV64IF-NEXT: # %bb.1:
; RV64IF-NEXT: li a0, 0
-; RV64IF-NEXT: andi s0, s0, 7
-; RV64IF-NEXT: bnez s0, .LBB1_2
-; RV64IF-NEXT: # %bb.1: # %if.end
+; RV64IF-NEXT: j .LBB1_3
+; RV64IF-NEXT: .LBB1_2: # %if.end
; RV64IF-NEXT: call fesetround
-; RV64IF-NEXT: addi s0, s0, -1
-; RV64IF-NEXT: seqz a0, s0
-; RV64IF-NEXT: .LBB1_2: # %return
+; RV64IF-NEXT: frrm a0
+; RV64IF-NEXT: slli a0, a0, 2
+; RV64IF-NEXT: srl a0, s0, a0
+; RV64IF-NEXT: andi a0, a0, 7
+; RV64IF-NEXT: addi a0, a0, -1
+; RV64IF-NEXT: seqz a0, a0
+; RV64IF-NEXT: .LBB1_3: # %return
; RV64IF-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64IF-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
; RV64IF-NEXT: .cfi_restore ra