[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCISelLowering.cpp PPCISelLowering.h PPCInstrInfo.td README_ALTIVEC.txt
Chris Lattner
lattner at cs.uiuc.edu
Tue Apr 18 10:59:48 PDT 2006
Changes in directory llvm/lib/Target/PowerPC:
PPCISelLowering.cpp updated: 1.164 -> 1.165
PPCISelLowering.h updated: 1.46 -> 1.47
PPCInstrInfo.td updated: 1.215 -> 1.216
README_ALTIVEC.txt updated: 1.29 -> 1.30
---
Log message:
Implement an important entry from README_ALTIVEC:
If an altivec predicate compare is used immediately by a branch, don't
use a (serializing) MFCR instruction to read the CR6 register, which requires
a compare to get it back to CR's. Instead, just branch on CR6 directly. :)
For example, for:
void foo2(vector float *A, vector float *B) {
if (!vec_any_eq(*A, *B))
*B = (vector float){0,0,0,0};
}
We now generate:
_foo2:
mfspr r2, 256
oris r5, r2, 12288
mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r5
lvx v2, 0, r4
lvx v3, 0, r3
vcmpeqfp. v2, v3, v2
bne cr6, LBB1_2 ; UnifiedReturnBlock
LBB1_1: ; cond_true
vxor v2, v2, v2
stvx v2, 0, r4
mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r2
blr
LBB1_2: ; UnifiedReturnBlock
mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r2
blr
instead of:
_foo2:
mfspr r2, 256
oris r5, r2, 12288
mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r5
lvx v2, 0, r4
lvx v3, 0, r3
vcmpeqfp. v2, v3, v2
mfcr r3, 2
rlwinm r3, r3, 27, 31, 31
cmpwi cr0, r3, 0
beq cr0, LBB1_2 ; UnifiedReturnBlock
LBB1_1: ; cond_true
vxor v2, v2, v2
stvx v2, 0, r4
mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r2
blr
LBB1_2: ; UnifiedReturnBlock
mtspr 256: http://llvm.cs.uiuc.edu/PR256 , r2
blr
This implements CodeGen/PowerPC/vec_br_cmp.ll.
---
Diffs of the changes: (+106 -24)
PPCISelLowering.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++++--------
PPCISelLowering.h | 9 ++++
PPCInstrInfo.td | 12 +++++-
README_ALTIVEC.txt | 6 ---
4 files changed, 106 insertions(+), 24 deletions(-)
Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff -u llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.164 llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.165
--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.164 Mon Apr 17 23:28:57 2006
+++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp Tue Apr 18 12:59:36 2006
@@ -246,6 +246,7 @@
// We have target-specific dag combine patterns for the following nodes:
setTargetDAGCombine(ISD::SINT_TO_FP);
setTargetDAGCombine(ISD::STORE);
+ setTargetDAGCombine(ISD::BR_CC);
computeRegisterProperties();
}
@@ -1460,18 +1461,17 @@
return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask);
}
-/// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom
-/// lower, do it, otherwise return null.
-static SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
- unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getValue();
-
- // If this is a lowered altivec predicate compare, CompareOpc is set to the
- // opcode number of the comparison.
- int CompareOpc = -1;
- bool isDot = false;
- switch (IntNo) {
- default: return SDOperand(); // Don't custom lower most intrinsics.
- // Comparison predicates.
+/// getAltivecCompareInfo - Given an intrinsic, return false if it is not an
+/// altivec comparison. If it is, return true and fill in Opc/isDot with
+/// information about the intrinsic.
+static bool getAltivecCompareInfo(SDOperand Intrin, int &CompareOpc,
+ bool &isDot) {
+ unsigned IntrinsicID = cast<ConstantSDNode>(Intrin.getOperand(0))->getValue();
+ CompareOpc = -1;
+ isDot = false;
+ switch (IntrinsicID) {
+ default: return false;
+ // Comparison predicates.
case Intrinsic::ppc_altivec_vcmpbfp_p: CompareOpc = 966; isDot = 1; break;
case Intrinsic::ppc_altivec_vcmpeqfp_p: CompareOpc = 198; isDot = 1; break;
case Intrinsic::ppc_altivec_vcmpequb_p: CompareOpc = 6; isDot = 1; break;
@@ -1501,10 +1501,20 @@
case Intrinsic::ppc_altivec_vcmpgtuh: CompareOpc = 582; isDot = 0; break;
case Intrinsic::ppc_altivec_vcmpgtuw: CompareOpc = 646; isDot = 0; break;
}
+ return true;
+}
+
+/// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom
+/// lower, do it, otherwise return null.
+static SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
+ // If this is a lowered altivec predicate compare, CompareOpc is set to the
+ // opcode number of the comparison.
+ int CompareOpc;
+ bool isDot;
+ if (!getAltivecCompareInfo(Op, CompareOpc, isDot))
+ return SDOperand(); // Don't custom lower most intrinsics.
- assert(CompareOpc>0 && "We only lower altivec predicate compares so far!");
-
- // If this is a non-dot comparison, make the VCMP node.
+ // If this is a non-dot comparison, make the VCMP node and we are done.
if (!isDot) {
SDOperand Tmp = DAG.getNode(PPCISD::VCMP, Op.getOperand(2).getValueType(),
Op.getOperand(1), Op.getOperand(2),
@@ -2198,6 +2208,69 @@
}
break;
}
+ case ISD::BR_CC: {
+ // If this is a branch on an altivec predicate comparison, lower this so
+ // that we don't have to do a MFCR: instead, branch directly on CR6. This
+ // lowering is done pre-legalize, because the legalizer lowers the predicate
+ // compare down to code that is difficult to reassemble.
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
+ SDOperand LHS = N->getOperand(2), RHS = N->getOperand(3);
+ int CompareOpc;
+ bool isDot;
+
+ if (LHS.getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
+ isa<ConstantSDNode>(RHS) && (CC == ISD::SETEQ || CC == ISD::SETNE) &&
+ getAltivecCompareInfo(LHS, CompareOpc, isDot)) {
+ assert(isDot && "Can't compare against a vector result!");
+
+ // If this is a comparison against something other than 0/1, then we know
+ // that the condition is never/always true.
+ unsigned Val = cast<ConstantSDNode>(RHS)->getValue();
+ if (Val != 0 && Val != 1) {
+ if (CC == ISD::SETEQ) // Cond never true, remove branch.
+ return N->getOperand(0);
+ // Always !=, turn it into an unconditional branch.
+ return DAG.getNode(ISD::BR, MVT::Other,
+ N->getOperand(0), N->getOperand(4));
+ }
+
+ bool BranchOnWhenPredTrue = (CC == ISD::SETEQ) ^ (Val == 0);
+
+ // Create the PPCISD altivec 'dot' comparison node.
+ std::vector<SDOperand> Ops;
+ std::vector<MVT::ValueType> VTs;
+ Ops.push_back(LHS.getOperand(2)); // LHS of compare
+ Ops.push_back(LHS.getOperand(3)); // RHS of compare
+ Ops.push_back(DAG.getConstant(CompareOpc, MVT::i32));
+ VTs.push_back(LHS.getOperand(2).getValueType());
+ VTs.push_back(MVT::Flag);
+ SDOperand CompNode = DAG.getNode(PPCISD::VCMPo, VTs, Ops);
+
+ // Unpack the result based on how the target uses it.
+ unsigned CompOpc;
+ switch (cast<ConstantSDNode>(LHS.getOperand(1))->getValue()) {
+ default: // Can't happen, don't crash on invalid number though.
+ case 0: // Branch on the value of the EQ bit of CR6.
+ CompOpc = BranchOnWhenPredTrue ? PPC::BEQ : PPC::BNE;
+ break;
+ case 1: // Branch on the inverted value of the EQ bit of CR6.
+ CompOpc = BranchOnWhenPredTrue ? PPC::BNE : PPC::BEQ;
+ break;
+ case 2: // Branch on the value of the LT bit of CR6.
+ CompOpc = BranchOnWhenPredTrue ? PPC::BLT : PPC::BGE;
+ break;
+ case 3: // Branch on the inverted value of the LT bit of CR6.
+ CompOpc = BranchOnWhenPredTrue ? PPC::BGE : PPC::BLT;
+ break;
+ }
+
+ return DAG.getNode(PPCISD::COND_BRANCH, MVT::Other, N->getOperand(0),
+ DAG.getRegister(PPC::CR6, MVT::i32),
+ DAG.getConstant(CompOpc, MVT::i32),
+ N->getOperand(4), CompNode.getValue(1));
+ }
+ break;
+ }
}
return SDOperand();
Index: llvm/lib/Target/PowerPC/PPCISelLowering.h
diff -u llvm/lib/Target/PowerPC/PPCISelLowering.h:1.46 llvm/lib/Target/PowerPC/PPCISelLowering.h:1.47
--- llvm/lib/Target/PowerPC/PPCISelLowering.h:1.46 Wed Apr 12 12:37:20 2006
+++ llvm/lib/Target/PowerPC/PPCISelLowering.h Tue Apr 18 12:59:36 2006
@@ -96,7 +96,14 @@
/// altivec VCMP*o instructions. For lack of better number, we use the
/// opcode number encoding for the OPC field to identify the compare. For
/// example, 838 is VCMPGTSH.
- VCMPo
+ VCMPo,
+
+ /// CHAIN = COND_BRANCH CHAIN, CRRC, OPC, DESTBB [, INFLAG] - This
+ /// corresponds to the COND_BRANCH pseudo instruction. CRRC is the
+ /// condition register to branch on, OPC is the branch opcode to use (e.g.
+ /// PPC::BLE), DESTBB is the destination block to branch to, and INFLAG is
+ /// an optional input flag argument.
+ COND_BRANCH
};
}
Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td
diff -u llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.215 llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.216
--- llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.215 Sat Apr 8 17:45:08 2006
+++ llvm/lib/Target/PowerPC/PPCInstrInfo.td Tue Apr 18 12:59:36 2006
@@ -34,6 +34,10 @@
SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>
]>;
+def SDT_PPCcondbr : SDTypeProfile<0, 3, [
+ SDTCisVT<1, i32>, SDTCisVT<2, OtherVT>
+]>;
+
//===----------------------------------------------------------------------===//
// PowerPC specific DAG Nodes.
//
@@ -74,6 +78,9 @@
def PPCvcmp : SDNode<"PPCISD::VCMP" , SDT_PPCvcmp, []>;
def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutFlag]>;
+def PPCcondbranch : SDNode<"PPCISD::COND_BRANCH", SDT_PPCcondbr,
+ [SDNPHasChain, SDNPOptInFlag]>;
+
//===----------------------------------------------------------------------===//
// PowerPC specific transformation functions and pattern fragments.
//
@@ -263,8 +270,9 @@
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1,
noResults = 1, PPC970_Unit = 7 in {
- def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc, target:$true),
- "; COND_BRANCH", []>;
+ def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc, target:$dst),
+ "; COND_BRANCH $crS, $opc, $dst",
+ [(PPCcondbranch CRRC:$crS, imm:$opc, bb:$dst)]>;
def B : IForm<18, 0, 0, (ops target:$dst),
"b $dst", BrB,
[(br bb:$dst)]>;
Index: llvm/lib/Target/PowerPC/README_ALTIVEC.txt
diff -u llvm/lib/Target/PowerPC/README_ALTIVEC.txt:1.29 llvm/lib/Target/PowerPC/README_ALTIVEC.txt:1.30
--- llvm/lib/Target/PowerPC/README_ALTIVEC.txt:1.29 Tue Apr 18 12:52:36 2006
+++ llvm/lib/Target/PowerPC/README_ALTIVEC.txt Tue Apr 18 12:59:36 2006
@@ -53,12 +53,6 @@
//===----------------------------------------------------------------------===//
-Do not generate the MFCR/RLWINM sequence for predicate compares when the
-predicate compare is used immediately by a branch. Just branch on the right
-cond code on CR6.
-
-//===----------------------------------------------------------------------===//
-
We need a way to teach tblgen that some operands of an intrinsic are required to
be constants. The verifier should enforce this constraint.
More information about the llvm-commits
mailing list