diff options
author | Nadav Rotem <nrotem@apple.com> | 2012-08-18 02:43:28 +0000 |
---|---|---|
committer | Nadav Rotem <nrotem@apple.com> | 2012-08-18 02:43:28 +0000 |
commit | b5838689c6e204af3677df0ae10167f6070aba00 (patch) | |
tree | a29c2cc54eadc0f0527df47a04fa9b5d489e35ac /lib | |
parent | fd45fa1503de725801be3db33c7e860298fc82a3 (diff) | |
download | external_llvm-b5838689c6e204af3677df0ae10167f6070aba00.zip external_llvm-b5838689c6e204af3677df0ae10167f6070aba00.tar.gz external_llvm-b5838689c6e204af3677df0ae10167f6070aba00.tar.bz2 |
The X86 backend has a number of optimizations for SETCC nodes which use
arithmetic instructions. However, when small data types are used, a truncate
node appears between the SETCC node and the arithmetic operation. This patch
adds support for this pattern.
Before:
xorl %esi, %edi
testb %dil, %dil
setne %al
ret
After:
xorb %dil, %sil
setne %al
ret
rdar://12081007
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162160 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index c77355f..79e99db 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -8283,7 +8283,18 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, unsigned Opcode = 0; unsigned NumOperands = 0; - switch (Op.getNode()->getOpcode()) { + + // Truncate operations may prevent the merge of the SETCC instruction + // and the arithmetic intruction before it. Attempt to truncate the operands + // of the arithmetic instruction and use a reduced bit-width instruction. + bool NeedTruncation = false; + unsigned InOpcode = Op.getNode()->getOpcode(); + if (Op->getOpcode() == ISD::TRUNCATE && Op->hasOneUse()) { + NeedTruncation = true; + InOpcode = Op->getOperand(0)->getOpcode(); + } + + switch (InOpcode) { case ISD::ADD: // Due to an isel shortcoming, be conservative if this add is likely to be // selected as part of a load-modify-store instruction. When the root node @@ -8339,7 +8350,7 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, if (User->getOpcode() != ISD::BRCOND && User->getOpcode() != ISD::SETCC && - (User->getOpcode() != ISD::SELECT || UOpNo != 0)) { + !(User->getOpcode() == ISD::SELECT && UOpNo == 0)) { NonFlagUse = true; break; } @@ -8360,11 +8371,9 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, goto default_case; // Otherwise use a regular EFLAGS-setting instruction. - switch (Op.getNode()->getOpcode()) { + switch (InOpcode) { default: llvm_unreachable("unexpected operator!"); - case ISD::SUB: - Opcode = X86ISD::SUB; - break; + case ISD::SUB: Opcode = X86ISD::SUB; break; case ISD::OR: Opcode = X86ISD::OR; break; case ISD::XOR: Opcode = X86ISD::XOR; break; case ISD::AND: Opcode = X86ISD::AND; break; @@ -8385,6 +8394,34 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, break; } + if (NeedTruncation) { + SDValue WideVal = Op->getOperand(0); + EVT VT = Op.getValueType(); + EVT WideVT = WideVal.getValueType(); + unsigned ConvertedOp = 0; + + // Use a target machine opcode to prevent further DAGCombine + // optimizations that may separate the arithmetic operations from the + // setcc node. + switch (WideVal.getOpcode()) { + default: break; + case ISD::ADD: ConvertedOp = X86ISD::ADD; break; + case ISD::SUB: ConvertedOp = X86ISD::SUB; break; + case ISD::AND: ConvertedOp = X86ISD::AND; break; + case ISD::OR: ConvertedOp = X86ISD::OR; break; + case ISD::XOR: ConvertedOp = X86ISD::XOR; break; + } + + if (ConvertedOp && WideVal.hasOneUse()) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (TLI.isOperationLegal(WideVal.getOpcode(), WideVT)) { + SDValue V0 = DAG.getNode(ISD::TRUNCATE, dl, VT, WideVal.getOperand(0)); + SDValue V1 = DAG.getNode(ISD::TRUNCATE, dl, VT, WideVal.getOperand(1)); + Op = DAG.getNode(ConvertedOp, dl, VT, V0, V1); + } + } + } + if (Opcode == 0) // Emit a CMP with 0, which is the TEST pattern. return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op, |