20
20
#include " llvm/CodeGen/MachineInstrBuilder.h"
21
21
#include " llvm/CodeGen/MachineRegisterInfo.h"
22
22
#include " llvm/CodeGen/TargetLoweringObjectFileImpl.h"
23
+ #include " llvm/IR/Intrinsics.h"
23
24
#include < cctype>
24
25
25
26
using namespace llvm ;
@@ -304,6 +305,9 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &tm,
304
305
// Codes for which we want to perform some z-specific combinations.
305
306
setTargetDAGCombine (ISD::SIGN_EXTEND);
306
307
308
+ // Handle intrinsics.
309
+ setOperationAction (ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
310
+
307
311
// We want to use MVC in preference to even a single load/store pair.
308
312
MaxStoresPerMemcpy = 0 ;
309
313
MaxStoresPerMemcpyOptSize = 0 ;
@@ -1031,6 +1035,53 @@ prepareVolatileOrAtomicLoad(SDValue Chain, SDLoc DL, SelectionDAG &DAG) const {
1031
1035
return DAG.getNode (SystemZISD::SERIALIZE, DL, MVT::Other, Chain);
1032
1036
}
1033
1037
1038
+ // Return true if Op is an intrinsic node with chain that returns the CC value
1039
+ // as its only (other) argument. Provide the associated SystemZISD opcode and
1040
+ // the mask of valid CC values if so.
1041
+ static bool isIntrinsicWithCCAndChain (SDValue Op, unsigned &Opcode,
1042
+ unsigned &CCValid) {
1043
+ unsigned Id = cast<ConstantSDNode>(Op.getOperand (1 ))->getZExtValue ();
1044
+ switch (Id) {
1045
+ case Intrinsic::s390_tbegin:
1046
+ Opcode = SystemZISD::TBEGIN;
1047
+ CCValid = SystemZ::CCMASK_TBEGIN;
1048
+ return true ;
1049
+
1050
+ case Intrinsic::s390_tbegin_nofloat:
1051
+ Opcode = SystemZISD::TBEGIN_NOFLOAT;
1052
+ CCValid = SystemZ::CCMASK_TBEGIN;
1053
+ return true ;
1054
+
1055
+ case Intrinsic::s390_tend:
1056
+ Opcode = SystemZISD::TEND;
1057
+ CCValid = SystemZ::CCMASK_TEND;
1058
+ return true ;
1059
+
1060
+ default :
1061
+ return false ;
1062
+ }
1063
+ }
1064
+
1065
+ // Emit an intrinsic with chain with a glued value instead of its CC result.
1066
+ static SDValue emitIntrinsicWithChainAndGlue (SelectionDAG &DAG, SDValue Op,
1067
+ unsigned Opcode) {
1068
+ // Copy all operands except the intrinsic ID.
1069
+ unsigned NumOps = Op.getNumOperands ();
1070
+ SmallVector<SDValue, 6 > Ops;
1071
+ Ops.reserve (NumOps - 1 );
1072
+ Ops.push_back (Op.getOperand (0 ));
1073
+ for (unsigned I = 2 ; I < NumOps; ++I)
1074
+ Ops.push_back (Op.getOperand (I));
1075
+
1076
+ assert (Op->getNumValues () == 2 && " Expected only CC result and chain" );
1077
+ SDVTList RawVTs = DAG.getVTList (MVT::Other, MVT::Glue);
1078
+ SDValue Intr = DAG.getNode (Opcode, SDLoc (Op), RawVTs, Ops);
1079
+ SDValue OldChain = SDValue (Op.getNode (), 1 );
1080
+ SDValue NewChain = SDValue (Intr.getNode (), 0 );
1081
+ DAG.ReplaceAllUsesOfValueWith (OldChain, NewChain);
1082
+ return Intr;
1083
+ }
1084
+
1034
1085
// CC is a comparison that will be implemented using an integer or
1035
1086
// floating-point comparison. Return the condition code mask for
1036
1087
// a branch on true. In the integer case, CCMASK_CMP_UO is set for
@@ -1588,9 +1639,53 @@ static void adjustForTestUnderMask(SelectionDAG &DAG, Comparison &C) {
1588
1639
C.CCMask = NewCCMask;
1589
1640
}
1590
1641
1642
+ // Return a Comparison that tests the condition-code result of intrinsic
1643
+ // node Call against constant integer CC using comparison code Cond.
1644
+ // Opcode is the opcode of the SystemZISD operation for the intrinsic
1645
+ // and CCValid is the set of possible condition-code results.
1646
+ static Comparison getIntrinsicCmp (SelectionDAG &DAG, unsigned Opcode,
1647
+ SDValue Call, unsigned CCValid, uint64_t CC,
1648
+ ISD::CondCode Cond) {
1649
+ Comparison C (Call, SDValue ());
1650
+ C.Opcode = Opcode;
1651
+ C.CCValid = CCValid;
1652
+ if (Cond == ISD::SETEQ)
1653
+ // bit 3 for CC==0, bit 0 for CC==3, always false for CC>3.
1654
+ C.CCMask = CC < 4 ? 1 << (3 - CC) : 0 ;
1655
+ else if (Cond == ISD::SETNE)
1656
+ // ...and the inverse of that.
1657
+ C.CCMask = CC < 4 ? ~(1 << (3 - CC)) : -1 ;
1658
+ else if (Cond == ISD::SETLT || Cond == ISD::SETULT)
1659
+ // bits above bit 3 for CC==0 (always false), bits above bit 0 for CC==3,
1660
+ // always true for CC>3.
1661
+ C.CCMask = CC < 4 ? -1 << (4 - CC) : -1 ;
1662
+ else if (Cond == ISD::SETGE || Cond == ISD::SETUGE)
1663
+ // ...and the inverse of that.
1664
+ C.CCMask = CC < 4 ? ~(-1 << (4 - CC)) : 0 ;
1665
+ else if (Cond == ISD::SETLE || Cond == ISD::SETULE)
1666
+ // bit 3 and above for CC==0, bit 0 and above for CC==3 (always true),
1667
+ // always true for CC>3.
1668
+ C.CCMask = CC < 4 ? -1 << (3 - CC) : -1 ;
1669
+ else if (Cond == ISD::SETGT || Cond == ISD::SETUGT)
1670
+ // ...and the inverse of that.
1671
+ C.CCMask = CC < 4 ? ~(-1 << (3 - CC)) : 0 ;
1672
+ else
1673
+ llvm_unreachable (" Unexpected integer comparison type" );
1674
+ C.CCMask &= CCValid;
1675
+ return C;
1676
+ }
1677
+
1591
1678
// Decide how to implement a comparison of type Cond between CmpOp0 with CmpOp1.
1592
1679
static Comparison getCmp (SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1,
1593
1680
ISD::CondCode Cond) {
1681
+ if (CmpOp1.getOpcode () == ISD::Constant) {
1682
+ uint64_t Constant = cast<ConstantSDNode>(CmpOp1)->getZExtValue ();
1683
+ unsigned Opcode, CCValid;
1684
+ if (CmpOp0.getOpcode () == ISD::INTRINSIC_W_CHAIN &&
1685
+ CmpOp0.getResNo () == 0 && CmpOp0->hasNUsesOfValue (1 , 0 ) &&
1686
+ isIntrinsicWithCCAndChain (CmpOp0, Opcode, CCValid))
1687
+ return getIntrinsicCmp (DAG, Opcode, CmpOp0, CCValid, Constant, Cond);
1688
+ }
1594
1689
Comparison C (CmpOp0, CmpOp1);
1595
1690
C.CCMask = CCMaskForCondCode (Cond);
1596
1691
if (C.Op0 .getValueType ().isFloatingPoint ()) {
@@ -1632,6 +1727,17 @@ static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1,
1632
1727
1633
1728
// Emit the comparison instruction described by C.
1634
1729
static SDValue emitCmp (SelectionDAG &DAG, SDLoc DL, Comparison &C) {
1730
+ if (!C.Op1 .getNode ()) {
1731
+ SDValue Op;
1732
+ switch (C.Op0 .getOpcode ()) {
1733
+ case ISD::INTRINSIC_W_CHAIN:
1734
+ Op = emitIntrinsicWithChainAndGlue (DAG, C.Op0 , C.Opcode );
1735
+ break ;
1736
+ default :
1737
+ llvm_unreachable (" Invalid comparison operands" );
1738
+ }
1739
+ return SDValue (Op.getNode (), Op->getNumValues () - 1 );
1740
+ }
1635
1741
if (C.Opcode == SystemZISD::ICMP)
1636
1742
return DAG.getNode (SystemZISD::ICMP, DL, MVT::Glue, C.Op0 , C.Op1 ,
1637
1743
DAG.getConstant (C.ICmpType , MVT::i32));
@@ -1713,7 +1819,6 @@ SDValue SystemZTargetLowering::lowerSETCC(SDValue Op,
1713
1819
}
1714
1820
1715
1821
SDValue SystemZTargetLowering::lowerBR_CC (SDValue Op, SelectionDAG &DAG) const {
1716
- SDValue Chain = Op.getOperand (0 );
1717
1822
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand (1 ))->get ();
1718
1823
SDValue CmpOp0 = Op.getOperand (2 );
1719
1824
SDValue CmpOp1 = Op.getOperand (3 );
@@ -1723,7 +1828,7 @@ SDValue SystemZTargetLowering::lowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
1723
1828
Comparison C (getCmp (DAG, CmpOp0, CmpOp1, CC));
1724
1829
SDValue Glue = emitCmp (DAG, DL, C);
1725
1830
return DAG.getNode (SystemZISD::BR_CCMASK, DL, Op.getValueType (),
1726
- Chain , DAG.getConstant (C.CCValid , MVT::i32),
1831
+ Op. getOperand ( 0 ) , DAG.getConstant (C.CCValid , MVT::i32),
1727
1832
DAG.getConstant (C.CCMask , MVT::i32), Dest, Glue);
1728
1833
}
1729
1834
@@ -2562,6 +2667,30 @@ SDValue SystemZTargetLowering::lowerPREFETCH(SDValue Op,
2562
2667
Node->getMemoryVT (), Node->getMemOperand ());
2563
2668
}
2564
2669
2670
+ // Return an i32 that contains the value of CC immediately after After,
2671
+ // whose final operand must be MVT::Glue.
2672
+ static SDValue getCCResult (SelectionDAG &DAG, SDNode *After) {
2673
+ SDValue Glue = SDValue (After, After->getNumValues () - 1 );
2674
+ SDValue IPM = DAG.getNode (SystemZISD::IPM, SDLoc (After), MVT::i32, Glue);
2675
+ return DAG.getNode (ISD::SRL, SDLoc (After), MVT::i32, IPM,
2676
+ DAG.getConstant (SystemZ::IPM_CC, MVT::i32));
2677
+ }
2678
+
2679
+ SDValue
2680
+ SystemZTargetLowering::lowerINTRINSIC_W_CHAIN (SDValue Op,
2681
+ SelectionDAG &DAG) const {
2682
+ unsigned Opcode, CCValid;
2683
+ if (isIntrinsicWithCCAndChain (Op, Opcode, CCValid)) {
2684
+ assert (Op->getNumValues () == 2 && " Expected only CC result and chain" );
2685
+ SDValue Glued = emitIntrinsicWithChainAndGlue (DAG, Op, Opcode);
2686
+ SDValue CC = getCCResult (DAG, Glued.getNode ());
2687
+ DAG.ReplaceAllUsesOfValueWith (SDValue (Op.getNode (), 0 ), CC);
2688
+ return SDValue ();
2689
+ }
2690
+
2691
+ return SDValue ();
2692
+ }
2693
+
2565
2694
SDValue SystemZTargetLowering::LowerOperation (SDValue Op,
2566
2695
SelectionDAG &DAG) const {
2567
2696
switch (Op.getOpcode ()) {
@@ -2635,6 +2764,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
2635
2764
return lowerSTACKRESTORE (Op, DAG);
2636
2765
case ISD::PREFETCH:
2637
2766
return lowerPREFETCH (Op, DAG);
2767
+ case ISD::INTRINSIC_W_CHAIN:
2768
+ return lowerINTRINSIC_W_CHAIN (Op, DAG);
2638
2769
default :
2639
2770
llvm_unreachable (" Unexpected node to lower" );
2640
2771
}
@@ -2675,6 +2806,9 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
2675
2806
OPCODE (SEARCH_STRING);
2676
2807
OPCODE (IPM);
2677
2808
OPCODE (SERIALIZE);
2809
+ OPCODE (TBEGIN);
2810
+ OPCODE (TBEGIN_NOFLOAT);
2811
+ OPCODE (TEND);
2678
2812
OPCODE (ATOMIC_SWAPW);
2679
2813
OPCODE (ATOMIC_LOADW_ADD);
2680
2814
OPCODE (ATOMIC_LOADW_SUB);
@@ -3502,6 +3636,50 @@ SystemZTargetLowering::emitStringWrapper(MachineInstr *MI,
3502
3636
return DoneMBB;
3503
3637
}
3504
3638
3639
+ // Update TBEGIN instruction with final opcode and register clobbers.
3640
+ MachineBasicBlock *
3641
+ SystemZTargetLowering::emitTransactionBegin (MachineInstr *MI,
3642
+ MachineBasicBlock *MBB,
3643
+ unsigned Opcode,
3644
+ bool NoFloat) const {
3645
+ MachineFunction &MF = *MBB->getParent ();
3646
+ const TargetFrameLowering *TFI = Subtarget.getFrameLowering ();
3647
+ const SystemZInstrInfo *TII = Subtarget.getInstrInfo ();
3648
+
3649
+ // Update opcode.
3650
+ MI->setDesc (TII->get (Opcode));
3651
+
3652
+ // We cannot handle a TBEGIN that clobbers the stack or frame pointer.
3653
+ // Make sure to add the corresponding GRSM bits if they are missing.
3654
+ uint64_t Control = MI->getOperand (2 ).getImm ();
3655
+ static const unsigned GPRControlBit[16 ] = {
3656
+ 0x8000 , 0x8000 , 0x4000 , 0x4000 , 0x2000 , 0x2000 , 0x1000 , 0x1000 ,
3657
+ 0x0800 , 0x0800 , 0x0400 , 0x0400 , 0x0200 , 0x0200 , 0x0100 , 0x0100
3658
+ };
3659
+ Control |= GPRControlBit[15 ];
3660
+ if (TFI->hasFP (MF))
3661
+ Control |= GPRControlBit[11 ];
3662
+ MI->getOperand (2 ).setImm (Control);
3663
+
3664
+ // Add GPR clobbers.
3665
+ for (int I = 0 ; I < 16 ; I++) {
3666
+ if ((Control & GPRControlBit[I]) == 0 ) {
3667
+ unsigned Reg = SystemZMC::GR64Regs[I];
3668
+ MI->addOperand (MachineOperand::CreateReg (Reg, true , true ));
3669
+ }
3670
+ }
3671
+
3672
+ // Add FPR clobbers.
3673
+ if (!NoFloat && (Control & 4 ) != 0 ) {
3674
+ for (int I = 0 ; I < 16 ; I++) {
3675
+ unsigned Reg = SystemZMC::FP64Regs[I];
3676
+ MI->addOperand (MachineOperand::CreateReg (Reg, true , true ));
3677
+ }
3678
+ }
3679
+
3680
+ return MBB;
3681
+ }
3682
+
3505
3683
MachineBasicBlock *SystemZTargetLowering::
3506
3684
EmitInstrWithCustomInserter (MachineInstr *MI, MachineBasicBlock *MBB) const {
3507
3685
switch (MI->getOpcode ()) {
@@ -3743,6 +3921,12 @@ EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const {
3743
3921
return emitStringWrapper (MI, MBB, SystemZ::MVST);
3744
3922
case SystemZ::SRSTLoop:
3745
3923
return emitStringWrapper (MI, MBB, SystemZ::SRST);
3924
+ case SystemZ::TBEGIN:
3925
+ return emitTransactionBegin (MI, MBB, SystemZ::TBEGIN, false );
3926
+ case SystemZ::TBEGIN_nofloat:
3927
+ return emitTransactionBegin (MI, MBB, SystemZ::TBEGIN, true );
3928
+ case SystemZ::TBEGINC:
3929
+ return emitTransactionBegin (MI, MBB, SystemZ::TBEGINC, true );
3746
3930
default :
3747
3931
llvm_unreachable (" Unexpected instr type to insert" );
3748
3932
}
0 commit comments