diff options
author | tstellar <tstellar@91177308-0d34-0410-b5e6-96231b3b80d8> | 2012-10-09 18:49:05 +0000 |
---|---|---|
committer | tstellar <tstellar@91177308-0d34-0410-b5e6-96231b3b80d8> | 2012-10-09 18:49:05 +0000 |
commit | 76b2b25443fb89754214b0cd2928d7d57e8e5c99 (patch) | |
tree | bad433a93272c85d646af6364dd76a5f66ce1f4c | |
parent | 6b24b44a2fa24c9987b9b8d753fa8ffa841e11ac (diff) |
R600: Prefer lowering SELECT_CC to CND* instructions over SET* instructions
SET* instructions are more expensive, because in some cases they require
additional instructions to convert their result to the correct type.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/R600/@165527 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/AMDGPU/R600ISelLowering.cpp | 92 | ||||
-rw-r--r-- | test/CodeGen/R600/fcmp-cnde-int-args.ll | 16 |
2 files changed, 66 insertions, 42 deletions
diff --git a/lib/Target/AMDGPU/R600ISelLowering.cpp b/lib/Target/AMDGPU/R600ISelLowering.cpp index be92f74b25f..121f49426e5 100644 --- a/lib/Target/AMDGPU/R600ISelLowering.cpp +++ b/lib/Target/AMDGPU/R600ISelLowering.cpp @@ -550,6 +550,56 @@ SDValue R600TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const // LHS and RHS are guaranteed to be the same value type EVT CompareVT = LHS.getValueType(); + // Check if we can lower this to a native operation. + + // Try to lower to a CND* instruction: + // CND* instructions requires RHS to be zero. Some SELECT_CC nodes that + // can be lowered to CND* instructions can also be lowered to SET* + // instructions. CND* instructions are cheaper, because they dont't + // require additional instructions to convert their result to the correct + // value type, so this check should be first. + if (isZero(LHS) || isZero(RHS)) { + SDValue Cond = (isZero(LHS) ? RHS : LHS); + SDValue Zero = (isZero(LHS) ? LHS : RHS); + ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get(); + if (CompareVT != VT) { + // Bitcast True / False to the correct types. This will end up being + // a nop, but it allows us to define only a single pattern in the + // .TD files for each CND* instruction rather than having to have + // one pattern for integer True/False and one for fp True/False + True = DAG.getNode(ISD::BITCAST, DL, CompareVT, True); + False = DAG.getNode(ISD::BITCAST, DL, CompareVT, False); + } + if (isZero(LHS)) { + CCOpcode = ISD::getSetCCSwappedOperands(CCOpcode); + } + + switch (CCOpcode) { + case ISD::SETONE: + case ISD::SETUNE: + case ISD::SETNE: + case ISD::SETULE: + case ISD::SETULT: + case ISD::SETOLE: + case ISD::SETOLT: + case ISD::SETLE: + case ISD::SETLT: + CCOpcode = ISD::getSetCCInverse(CCOpcode, CompareVT == MVT::i32); + Temp = True; + True = False; + False = Temp; + break; + default: + break; + } + SDValue SelectNode = DAG.getNode(ISD::SELECT_CC, DL, CompareVT, + Cond, Zero, + True, False, + DAG.getCondCode(CCOpcode)); + return DAG.getNode(ISD::BITCAST, DL, VT, SelectNode); + } + + // Try to lower to a SET* instruction: // We need all the operands of SELECT_CC to have the same value type, so if // necessary we need to change True and False to be the same type as LHS and // RHS, and then convert the result of the select_cc back to the correct type. @@ -592,48 +642,6 @@ SDValue R600TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const if (isHWTrueValue(False) && isHWFalseValue(True)) { } - // Check if we can lower this to a native operation. - // CND* instructions requires all operands to have the same type, - // and RHS to be zero. - - if (isZero(LHS) || isZero(RHS)) { - SDValue Cond = (isZero(LHS) ? RHS : LHS); - SDValue Zero = (isZero(LHS) ? LHS : RHS); - ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get(); - if (CompareVT != VT) { - True = DAG.getNode(ISD::BITCAST, DL, CompareVT, True); - False = DAG.getNode(ISD::BITCAST, DL, CompareVT, False); - } - if (isZero(LHS)) { - CCOpcode = ISD::getSetCCSwappedOperands(CCOpcode); - } - - switch (CCOpcode) { - case ISD::SETONE: - case ISD::SETUNE: - case ISD::SETNE: - case ISD::SETULE: - case ISD::SETULT: - case ISD::SETOLE: - case ISD::SETOLT: - case ISD::SETLE: - case ISD::SETLT: - CCOpcode = ISD::getSetCCInverse(CCOpcode, CompareVT == MVT::i32); - Temp = True; - True = False; - False = Temp; - break; - default: - break; - } - SDValue SelectNode = DAG.getNode(ISD::SELECT_CC, DL, CompareVT, - Cond, Zero, - True, False, - DAG.getCondCode(CCOpcode)); - return DAG.getNode(ISD::BITCAST, DL, VT, SelectNode); - } - - // If we make it this for it means we have no native instructions to handle // this SELECT_CC, so we must lower it. SDValue HWTrue, HWFalse; diff --git a/test/CodeGen/R600/fcmp-cnde-int-args.ll b/test/CodeGen/R600/fcmp-cnde-int-args.ll new file mode 100644 index 00000000000..92f3b5fb403 --- /dev/null +++ b/test/CodeGen/R600/fcmp-cnde-int-args.ll @@ -0,0 +1,16 @@ +;RUN: llc < %s -march=r600 -mcpu=redwood | FileCheck %s + +; This test checks a bug in R600TargetLowering::LowerSELECT_CC where the +; chance to optimize the fcmp + select instructions to CNDE was missed +; due to the fact that the operands to fcmp and select had different types + +;CHECK: CNDE T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} + +define void @test(i32 addrspace(1)* %out, float addrspace(1)* %in) { +entry: + %0 = load float addrspace(1)* %in + %cmp = fcmp oeq float %0, 0.000000e+00 + %value = select i1 %cmp, i32 -1, i32 0 + store i32 %value, i32 addrspace(1)* %out + ret void +} |