summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelDAGToDAG.cpp')
-rw-r--r--llvm/lib/Target/X86/X86ISelDAGToDAG.cpp78
1 files changed, 56 insertions, 22 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index cbc8eee28b0..e325d975486 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -3073,33 +3073,67 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
return;
}
+ // For example, "testl %eax, $2048" to "testb %ah, $8".
+ if (isShiftedUInt<8, 8>(Mask) &&
+ (!(Mask & 0x8000) || hasNoSignedComparisonUses(Node))) {
+ // Shift the immediate right by 8 bits.
+ SDValue ShiftedImm = CurDAG->getTargetConstant(Mask >> 8, dl, MVT::i8);
+ SDValue Reg = N0.getOperand(0);
+
+ // Extract the h-register.
+ SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl,
+ MVT::i8, Reg);
+
+ // Emit a testb. The EXTRACT_SUBREG becomes a COPY that can only
+ // target GR8_NOREX registers, so make sure the register class is
+ // forced.
+ SDNode *NewNode = CurDAG->getMachineNode(X86::TEST8ri_NOREX, dl,
+ MVT::i32, Subreg, ShiftedImm);
+ // Replace SUB|CMP with TEST, since SUB has two outputs while TEST has
+ // one, do not call ReplaceAllUsesWith.
+ ReplaceUses(SDValue(Node, (Opcode == X86ISD::SUB ? 1 : 0)),
+ SDValue(NewNode, 0));
+ CurDAG->RemoveDeadNode(Node);
+ return;
+ }
+
+ // For example, "testl %eax, $32776" to "testw %ax, $32776".
+ // NOTE: We only want to form TESTW instructions if optimizing for
+ // min size. Otherwise we only save one byte and possibly get a length
+ // changing prefix penalty in the decoders.
+ if (OptForMinSize && isUInt<16>(Mask) && N0.getValueType() != MVT::i16 &&
+ (!(Mask & 0x8000) || hasNoSignedComparisonUses(Node))) {
+ SDValue Imm = CurDAG->getTargetConstant(Mask, dl, MVT::i16);
+ SDValue Reg = N0.getOperand(0);
+
+ // Extract the 16-bit subregister.
+ SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::sub_16bit, dl,
+ MVT::i16, Reg);
+
+ // Emit a testw.
+ SDNode *NewNode = CurDAG->getMachineNode(X86::TEST16ri, dl, MVT::i32,
+ Subreg, Imm);
+ // Replace SUB|CMP with TEST, since SUB has two outputs while TEST has
+ // one, do not call ReplaceAllUsesWith.
+ ReplaceUses(SDValue(Node, (Opcode == X86ISD::SUB ? 1 : 0)),
+ SDValue(NewNode, 0));
+ CurDAG->RemoveDeadNode(Node);
+ return;
+ }
+
// For example, "testq %rax, $268468232" to "testl %eax, $268468232".
- if (isUInt<32>(Mask) &&
+ if (isUInt<32>(Mask) && N0.getValueType() == MVT::i64 &&
(!(Mask & 0x80000000) || hasNoSignedComparisonUses(Node))) {
- MVT VT = MVT::i32;
- int SubRegOp = X86::sub_32bit;
- unsigned Op = X86::TEST32ri;
-
- // For example, "testl %eax, $32776" to "testw %ax, $32776".
- // NOTE: We only want to form TESTW instructions if optimizing for
- // min size. Otherwise we only save one byte and possibly get a length
- // changing prefix penalty in the decoders.
- if (OptForMinSize && isUInt<16>(Mask) &&
- (!(Mask & 0x8000) || hasNoSignedComparisonUses(Node))) {
- VT = MVT::i16;
- SubRegOp = X86::sub_16bit;
- Op = X86::TEST16ri;
- }
-
- SDValue Imm = CurDAG->getTargetConstant(Mask, dl, VT);
+ SDValue Imm = CurDAG->getTargetConstant(Mask, dl, MVT::i32);
SDValue Reg = N0.getOperand(0);
- // Extract the subregister if necessary.
- if (N0.getValueType() != VT)
- Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT, Reg);
+ // Extract the 32-bit subregister.
+ SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::sub_32bit, dl,
+ MVT::i32, Reg);
- // Emit a testl or testw.
- SDNode *NewNode = CurDAG->getMachineNode(Op, dl, MVT::i32, Reg, Imm);
+ // Emit a testl.
+ SDNode *NewNode = CurDAG->getMachineNode(X86::TEST32ri, dl, MVT::i32,
+ Subreg, Imm);
// Replace SUB|CMP with TEST, since SUB has two outputs while TEST has
// one, do not call ReplaceAllUsesWith.
ReplaceUses(SDValue(Node, (Opcode == X86ISD::SUB ? 1 : 0)),
OpenPOWER on IntegriCloud