Commit e0c1ea44 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r261306:

------------------------------------------------------------------------
r261306 | matze | 2016-02-18 20:44:19 -0800 (Thu, 18 Feb 2016) | 1 line

LegalizeDAG: Fix ExpandFCOPYSIGN assuming the same type on both inputs
------------------------------------------------------------------------

llvm-svn: 261334
parent 50a6cde3
Loading
Loading
Loading
Loading
+31 −5
Original line number Diff line number Diff line
@@ -1637,6 +1637,7 @@ struct FloatSignAsInt {
  MachinePointerInfo FloatPointerInfo;
  SDValue IntValue;
  APInt SignMask;
  uint8_t SignBit;
};
}

@@ -1653,6 +1654,7 @@ void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State,
  if (TLI.isTypeLegal(IVT)) {
    State.IntValue = DAG.getNode(ISD::BITCAST, DL, IVT, Value);
    State.SignMask = APInt::getSignBit(NumBits);
    State.SignBit = NumBits - 1;
    return;
  }

@@ -1689,6 +1691,7 @@ void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State,
                                  IntPtr, State.IntPointerInfo, MVT::i8,
                                  false, false, false, 0);
  State.SignMask = APInt::getOneBitSet(LoadTy.getSizeInBits(), 7);
  State.SignBit = 7;
}

/// Replace the integer value produced by getSignAsIntValue() with a new value
@@ -1731,15 +1734,38 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
    return DAG.getSelect(DL, FloatVT, Cond, NegValue, AbsValue);
  }

  // Transform values to integer, copy the sign bit and transform back.
  // Transform Mag value to integer, and clear the sign bit.
  FloatSignAsInt MagAsInt;
  getSignAsIntValue(MagAsInt, DL, Mag);
  assert(SignAsInt.SignMask == MagAsInt.SignMask);
  SDValue ClearSignMask = DAG.getConstant(~SignAsInt.SignMask, DL, IntVT);
  SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, MagAsInt.IntValue,
  EVT MagVT = MagAsInt.IntValue.getValueType();
  SDValue ClearSignMask = DAG.getConstant(~MagAsInt.SignMask, DL, MagVT);
  SDValue ClearedSign = DAG.getNode(ISD::AND, DL, MagVT, MagAsInt.IntValue,
                                    ClearSignMask);
  SDValue CopiedSign = DAG.getNode(ISD::OR, DL, IntVT, ClearedSign, SignBit);

  // Get the signbit at the right position for MagAsInt.
  int ShiftAmount = SignAsInt.SignBit - MagAsInt.SignBit;
  if (SignBit.getValueSizeInBits() > ClearedSign.getValueSizeInBits()) {
    if (ShiftAmount > 0) {
      SDValue ShiftCnst = DAG.getConstant(ShiftAmount, DL, IntVT);
      SignBit = DAG.getNode(ISD::SRL, DL, IntVT, SignBit, ShiftCnst);
    } else if (ShiftAmount < 0) {
      SDValue ShiftCnst = DAG.getConstant(-ShiftAmount, DL, IntVT);
      SignBit = DAG.getNode(ISD::SHL, DL, IntVT, SignBit, ShiftCnst);
    }
    SignBit = DAG.getNode(ISD::TRUNCATE, DL, MagVT, SignBit);
  } else if (SignBit.getValueSizeInBits() < ClearedSign.getValueSizeInBits()) {
    SignBit = DAG.getNode(ISD::ZERO_EXTEND, DL, MagVT, SignBit);
    if (ShiftAmount > 0) {
      SDValue ShiftCnst = DAG.getConstant(ShiftAmount, DL, MagVT);
      SignBit = DAG.getNode(ISD::SRL, DL, MagVT, SignBit, ShiftCnst);
    } else if (ShiftAmount < 0) {
      SDValue ShiftCnst = DAG.getConstant(-ShiftAmount, DL, MagVT);
      SignBit = DAG.getNode(ISD::SHL, DL, MagVT, SignBit, ShiftCnst);
    }
  }

  // Store the part with the modified sign and convert back to float.
  SDValue CopiedSign = DAG.getNode(ISD::OR, DL, MagVT, ClearedSign, SignBit);
  return modifySignAsInt(MagAsInt, DL, CopiedSign);
}

+23 −0
Original line number Diff line number Diff line
; RUN: llc -o - %s | FileCheck %s
; Check that selection dag legalization of fcopysign works in cases with
; different modes for the arguments.
target triple = "aarch64--"

declare fp128 @llvm.copysign.f128(fp128, fp128)

@val = global double zeroinitializer, align 8

; CHECK-LABEL: copysign0
; CHECK: ldr [[REG:x[0-9]+]], [x8, :lo12:val]
; CHECK: and [[ANDREG:x[0-9]+]], [[REG]], #0x8000000000000000
; CHECK: lsr x[[LSRREGNUM:[0-9]+]], [[ANDREG]], #56
; CHECK: bfxil w[[LSRREGNUM]], w{{[0-9]+}}, #0, #7
; CHECK: strb w[[LSRREGNUM]],
; CHECK: ldr q{{[0-9]+}},
define fp128 @copysign0() {
entry:
  %v = load double, double* @val, align 8
  %conv = fpext double %v to fp128
  %call = tail call fp128 @llvm.copysign.f128(fp128 0xL00000000000000007FFF000000000000, fp128 %conv) #2
  ret fp128 %call
}