forked from OSchip/llvm-project
[FPEnv][ARM] Implement lowering of llvm.set.rounding
Differential Revision: https://reviews.llvm.org/D96501
This commit is contained in:
parent
af186e9372
commit
816053bc71
|
@ -1343,6 +1343,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
|||
// iff target supports vfp2.
|
||||
setOperationAction(ISD::BITCAST, MVT::i64, Custom);
|
||||
setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SET_ROUNDING, MVT::Other, Custom);
|
||||
}
|
||||
|
||||
// We want to custom lower some of our intrinsics.
|
||||
|
@ -6118,6 +6119,48 @@ SDValue ARMTargetLowering::LowerFLT_ROUNDS_(SDValue Op,
|
|||
return DAG.getMergeValues({And, Chain}, dl);
|
||||
}
|
||||
|
||||
SDValue ARMTargetLowering::LowerSET_ROUNDING(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDLoc DL(Op);
|
||||
SDValue Chain = Op->getOperand(0);
|
||||
SDValue RMValue = Op->getOperand(1);
|
||||
|
||||
// The rounding mode is in bits 23:22 of the FPSCR.
|
||||
// The llvm.set.rounding argument value to ARM rounding mode value mapping
|
||||
// is 0->3, 1->0, 2->1, 3->2. The formula we use to implement this is
|
||||
// ((arg - 1) & 3) << 22).
|
||||
//
|
||||
// It is expected that the argument of llvm.set.rounding is within the
|
||||
// segment [0, 3], so NearestTiesToAway (4) is not handled here. It is
|
||||
// responsibility of the code generated llvm.set.rounding to ensure this
|
||||
// condition.
|
||||
|
||||
// Calculate new value of FPSCR[23:22].
|
||||
RMValue = DAG.getNode(ISD::SUB, DL, MVT::i32, RMValue,
|
||||
DAG.getConstant(1, DL, MVT::i32));
|
||||
RMValue = DAG.getNode(ISD::AND, DL, MVT::i32, RMValue,
|
||||
DAG.getConstant(0x3, DL, MVT::i32));
|
||||
RMValue = DAG.getNode(ISD::SHL, DL, MVT::i32, RMValue,
|
||||
DAG.getConstant(ARM::RoundingBitsPos, DL, MVT::i32));
|
||||
|
||||
// Get current value of FPSCR.
|
||||
SDValue Ops[] = {Chain,
|
||||
DAG.getConstant(Intrinsic::arm_get_fpscr, DL, MVT::i32)};
|
||||
SDValue FPSCR =
|
||||
DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i32, MVT::Other}, Ops);
|
||||
Chain = FPSCR.getValue(1);
|
||||
FPSCR = FPSCR.getValue(0);
|
||||
|
||||
// Put new rounding mode into FPSCR[23:22].
|
||||
const unsigned RMMask = ~(ARM::Rounding::rmMask << ARM::RoundingBitsPos);
|
||||
FPSCR = DAG.getNode(ISD::AND, DL, MVT::i32, FPSCR,
|
||||
DAG.getConstant(RMMask, DL, MVT::i32));
|
||||
FPSCR = DAG.getNode(ISD::OR, DL, MVT::i32, FPSCR, RMValue);
|
||||
SDValue Ops2[] = {
|
||||
Chain, DAG.getConstant(Intrinsic::arm_set_fpscr, DL, MVT::i32), FPSCR};
|
||||
return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
|
||||
}
|
||||
|
||||
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG,
|
||||
const ARMSubtarget *ST) {
|
||||
SDLoc dl(N);
|
||||
|
@ -9849,6 +9892,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
|||
case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG, Subtarget);
|
||||
case ISD::TRUNCATE: return LowerTruncatei1(Op, DAG, Subtarget);
|
||||
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
|
||||
case ISD::SET_ROUNDING: return LowerSET_ROUNDING(Op, DAG);
|
||||
case ISD::MUL: return LowerMUL(Op, DAG);
|
||||
case ISD::SDIV:
|
||||
if (Subtarget->isTargetWindows() && !Op.getValueType().isVector())
|
||||
|
|
|
@ -332,6 +332,21 @@ class VectorType;
|
|||
|
||||
} // end namespace ARMISD
|
||||
|
||||
namespace ARM {
|
||||
/// Possible values of current rounding mode, which is specified in bits
|
||||
/// 23:22 of FPSCR.
|
||||
enum Rounding {
|
||||
RN = 0, // Round to Nearest
|
||||
RP = 1, // Round towards Plus infinity
|
||||
RM = 2, // Round towards Minus infinity
|
||||
RZ = 3, // Round towards Zero
|
||||
rmMask = 3 // Bit mask selecting rounding mode
|
||||
};
|
||||
|
||||
// Bit position of rounding mode bits in FPSCR.
|
||||
const unsigned RoundingBitsPos = 22;
|
||||
} // namespace ARM
|
||||
|
||||
/// Define some predicates that are used for node matching.
|
||||
namespace ARM {
|
||||
|
||||
|
@ -767,6 +782,7 @@ class VectorType;
|
|||
SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerConstantFP(SDValue Op, SelectionDAG &DAG,
|
||||
const ARMSubtarget *ST) const;
|
||||
SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
; RUN: llc -mtriple=arm-eabi -float-abi=soft -mattr=+vfp2 %s -o - | FileCheck %s
|
||||
|
||||
define void @func_02(i32 %rm) {
|
||||
call void @llvm.set.rounding(i32 %rm)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: func_02:
|
||||
; CHECK: vmrs r1, fpscr
|
||||
; CHECK: sub r0, r0, #1
|
||||
; CHECK: and r0, r0, #3
|
||||
; CHECK: bic r1, r1, #12582912
|
||||
; CHECK: orr r0, r1, r0, lsl #22
|
||||
; CHECK: vmsr fpscr, r0
|
||||
; CHECK: mov pc, lr
|
||||
|
||||
|
||||
define void @func_03() {
|
||||
call void @llvm.set.rounding(i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: func_03
|
||||
; CHECK: vmrs r0, fpscr
|
||||
; CHECK: orr r0, r0, #12582912
|
||||
; CHECK: vmsr fpscr, r0
|
||||
; CHECK: mov pc, lr
|
||||
|
||||
|
||||
define void @func_04() {
|
||||
call void @llvm.set.rounding(i32 1)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: func_04
|
||||
; CHECK: vmrs r0, fpscr
|
||||
; CHECK: bic r0, r0, #12582912
|
||||
; CHECK: vmsr fpscr, r0
|
||||
; CHECK: mov pc, lr
|
||||
|
||||
|
||||
define void @func_05() {
|
||||
call void @llvm.set.rounding(i32 2)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
; CHECK-LABEL: func_05
|
||||
; CHECK: vmrs r0, fpscr
|
||||
; CHECK: bic r0, r0, #12582912
|
||||
; CHECK: orr r0, r0, #4194304
|
||||
; CHECK: vmsr fpscr, r0
|
||||
; CHECK: mov pc, lr
|
||||
|
||||
|
||||
define void @func_06() {
|
||||
call void @llvm.set.rounding(i32 3)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: func_06
|
||||
; CHECK: vmrs r0, fpscr
|
||||
; CHECK: bic r0, r0, #12582912
|
||||
; CHECK: orr r0, r0, #8388608
|
||||
; CHECK: vmsr fpscr, r0
|
||||
; CHECK: mov pc, lr
|
||||
|
||||
|
||||
declare void @llvm.set.rounding(i32)
|
Loading…
Reference in New Issue