switch (IntrinsicID) {
default: return Op;
+ case AMDGPUIntrinsic::AMDIL_abs:
+ return LowerIntrinsicIABS(Op, DAG);
case AMDGPUIntrinsic::AMDIL_max:
return DAG.getNode(AMDGPUISD::FMAX, DL, VT, Op.getOperand(1),
Op.getOperand(2));
}
}
+///IABS(a) = SMAX(sub(0, a), a)
+SDValue AMDGPUTargetLowering::LowerIntrinsicIABS(SDValue Op,
+ SelectionDAG &DAG) const
+{
+
+ DebugLoc DL = Op.getDebugLoc();
+ EVT VT = Op.getValueType();
+ SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, VT),
+ Op.getOperand(1));
+
+ return DAG.getNode(AMDGPUISD::SMAX, DL, VT, Neg, Op.getOperand(1));
+}
+
void AMDGPUTargetLowering::addLiveIn(MachineInstr * MI,
MachineFunction * MF, MachineRegisterInfo & MRI,
const TargetInstrInfo * TII, unsigned reg) const
AMDGPUTargetLowering(TargetMachine &TM);
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerIntrinsicIABS(SDValue Op, SelectionDAG &DAG) const;
virtual const char* getTargetNodeName(unsigned Opcode) const;
};
defm IFFB_HI : UnaryOpMCi32<IL_OP_I_FFB_HI, IL_ffb_hi>;
defm IFFB_LO : UnaryOpMCi32<IL_OP_I_FFB_LO, IL_ffb_lo>;
let mayLoad = 0, mayStore = 0 in {
-defm ABS : UnaryIntrinsicInt<IL_OP_ABS, int_AMDIL_abs>;
defm BITCOUNT : UnaryIntrinsicInt<IL_OP_IBIT_COUNT, int_AMDIL_bit_count_i32>;
defm FFB_LO : UnaryIntrinsicInt<IL_OP_I_FFB_LO, int_AMDIL_bit_find_first_lo>;
defm FFB_HI : UnaryIntrinsicInt<IL_OP_I_FFB_HI, int_AMDIL_bit_find_first_hi>;
.addOperand(MI.getOperand(1));
break;
- case AMDIL::ABS_i32:
- {
- unsigned neg = MRI->createVirtualRegister(
- &AMDIL::R600_TReg32RegClass);
- BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDIL::SUB_INT),neg)
- .addReg(AMDIL::ZERO)
- .addOperand(MI.getOperand(1));
-
- BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDIL::MAX_INT))
- .addOperand(MI.getOperand(0))
- .addOperand(MI.getOperand(1))
- .addReg(neg);
-
- break;
- }
-
/* XXX: We could propagate the ABS flag to all of the uses of Operand0 and
* remove the ABS instruction.*/
case AMDIL::FABS_f32: