[PowerPC] Fix FLT_ROUNDS_ on little endian
authorQiu Chaofan <qiucofan@cn.ibm.com>
Wed, 2 Dec 2020 09:12:20 +0000 (17:12 +0800)
committerQiu Chaofan <qiucofan@cn.ibm.com>
Wed, 2 Dec 2020 09:16:32 +0000 (17:16 +0800)
In lowering of FLT_ROUNDS_, FPSCR content will be moved into FP register
and then GPR, and then truncated into word.

For subtargets without direct move support, it will store and then load.
The load address needs adjustment (+4) only on big-endian targets. This
patch fixes it on using generic opcodes on little-endian and subtargets
with direct-move.

Reviewed By: steven.zhang

Differential Revision: https://reviews.llvm.org/D91845

llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/test/CodeGen/PowerPC/frounds.ll

index 1864dc7..f9f84aa 100644 (file)
@@ -8975,16 +8975,24 @@ SDValue PPCTargetLowering::LowerFLT_ROUNDS_(SDValue Op,
   SDValue MFFS = DAG.getNode(PPCISD::MFFS, dl, {MVT::f64, MVT::Other}, Chain);
   Chain = MFFS.getValue(1);
 
-  // Save FP register to stack slot
-  int SSFI = MF.getFrameInfo().CreateStackObject(8, Align(8), false);
-  SDValue StackSlot = DAG.getFrameIndex(SSFI, PtrVT);
-  Chain = DAG.getStore(Chain, dl, MFFS, StackSlot, MachinePointerInfo());
-
-  // Load FP Control Word from low 32 bits of stack slot.
-  SDValue Four = DAG.getConstant(4, dl, PtrVT);
-  SDValue Addr = DAG.getNode(ISD::ADD, dl, PtrVT, StackSlot, Four);
-  SDValue CWD = DAG.getLoad(MVT::i32, dl, Chain, Addr, MachinePointerInfo());
-  Chain = CWD.getValue(1);
+  SDValue CWD;
+  if (isTypeLegal(MVT::i64)) {
+    CWD = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32,
+                      DAG.getNode(ISD::BITCAST, dl, MVT::i64, MFFS));
+  } else {
+    // Save FP register to stack slot
+    int SSFI = MF.getFrameInfo().CreateStackObject(8, Align(8), false);
+    SDValue StackSlot = DAG.getFrameIndex(SSFI, PtrVT);
+    Chain = DAG.getStore(Chain, dl, MFFS, StackSlot, MachinePointerInfo());
+
+    // Load FP Control Word from low 32 bits of stack slot.
+    assert(hasBigEndianPartOrdering(MVT::i64, MF.getDataLayout()) &&
+           "Stack slot adjustment is valid only on big endian subtargets!");
+    SDValue Four = DAG.getConstant(4, dl, PtrVT);
+    SDValue Addr = DAG.getNode(ISD::ADD, dl, PtrVT, StackSlot, Four);
+    CWD = DAG.getLoad(MVT::i32, dl, Chain, Addr, MachinePointerInfo());
+    Chain = CWD.getValue(1);
+  }
 
   // Transform as necessary
   SDValue CWD1 =
index df339ce..277423f 100644 (file)
@@ -42,7 +42,7 @@ define i32 @foo() {
 ; PPC64LE:       # %bb.0: # %entry
 ; PPC64LE-NEXT:    mffs 0
 ; PPC64LE-NEXT:    stfd 0, -16(1)
-; PPC64LE-NEXT:    lwz 3, -12(1)
+; PPC64LE-NEXT:    lwz 3, -16(1)
 ; PPC64LE-NEXT:    not 4, 3
 ; PPC64LE-NEXT:    clrlwi 3, 3, 30
 ; PPC64LE-NEXT:    rlwinm 4, 4, 31, 31, 31
@@ -54,8 +54,7 @@ define i32 @foo() {
 ; DM-LABEL: foo:
 ; DM:       # %bb.0: # %entry
 ; DM-NEXT:    mffs 0
-; DM-NEXT:    stfd 0, -16(1)
-; DM-NEXT:    lwz 3, -12(1)
+; DM-NEXT:    mffprd 3, 0
 ; DM-NEXT:    not 4, 3
 ; DM-NEXT:    clrlwi 3, 3, 30
 ; DM-NEXT:    rlwinm 4, 4, 31, 31, 31