[llvm-commits] [llvm] r79439 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAG.h lib/CodeGen/SelectionDAG/SelectionDAG.cpp lib/Target/X86/X86ISelDAGToDAG.cpp test/CodeGen/X86/live-out-reg-info.ll test/CodeGen/X86/test-shrink.ll
Dan Gohman
gohman at apple.com
Wed Aug 19 11:16:18 PDT 2009
Author: djg
Date: Wed Aug 19 13:16:17 2009
New Revision: 79439
URL: http://llvm.org/viewvc/llvm-project?rev=79439&view=rev
Log:
Add an x86 peep that narrows TEST instructions to forms that use
a smaller encoding. These kinds of patterns are very frequent in
sqlite3, for example.
Added:
llvm/trunk/test/CodeGen/X86/test-shrink.ll
Modified:
llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
llvm/trunk/test/CodeGen/X86/live-out-reg-info.ll
Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=79439&r1=79438&r2=79439&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Wed Aug 19 13:16:17 2009
@@ -686,6 +686,11 @@
const std::vector<EVT> &ResultTys, const SDValue *Ops,
unsigned NumOps);
+ /// getTargetExtractSubreg - A convenience function for creating
+ /// TargetInstrInfo::EXTRACT_SUBREG nodes.
+ SDValue getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT,
+ SDValue Operand);
+
/// getNodeIfExists - Get the specified node if it's already available, or
/// else return NULL.
SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs,
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=79439&r1=79438&r2=79439&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Aug 19 13:16:17 2009
@@ -4586,6 +4586,17 @@
return getNode(~Opcode, dl, ResultTys, Ops, NumOps).getNode();
}
+/// getTargetExtractSubreg - A convenience function for creating
+/// TargetInstrInfo::EXTRACT_SUBREG nodes.
+SDValue
+SelectionDAG::getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT,
+ SDValue Operand) {
+ SDValue SRIdxVal = getTargetConstant(SRIdx, MVT::i32);
+ SDNode *Subreg = getTargetNode(TargetInstrInfo::EXTRACT_SUBREG, DL,
+ VT, Operand, SRIdxVal);
+ return SDValue(Subreg, 0);
+}
+
/// getNodeIfExists - Get the specified node if it's already available, or
/// else return NULL.
SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList,
Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=79439&r1=79438&r2=79439&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Wed Aug 19 13:16:17 2009
@@ -1743,9 +1743,8 @@
Result,
CurDAG->getTargetConstant(8, MVT::i8)), 0);
// Then truncate it down to i8.
- SDValue SRIdx = CurDAG->getTargetConstant(X86::SUBREG_8BIT, MVT::i32);
- Result = SDValue(CurDAG->getTargetNode(X86::EXTRACT_SUBREG, dl,
- MVT::i8, Result, SRIdx), 0);
+ Result = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT, dl,
+ MVT::i8, Result);
} else {
Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
HiReg, NVT, InFlag);
@@ -1919,9 +1918,8 @@
CurDAG->getTargetConstant(8, MVT::i8)),
0);
// Then truncate it down to i8.
- SDValue SRIdx = CurDAG->getTargetConstant(X86::SUBREG_8BIT, MVT::i32);
- Result = SDValue(CurDAG->getTargetNode(X86::EXTRACT_SUBREG, dl,
- MVT::i8, Result, SRIdx), 0);
+ Result = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT, dl,
+ MVT::i8, Result);
} else {
Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
HiReg, NVT, InFlag);
@@ -1944,6 +1942,105 @@
return NULL;
}
+ case X86ISD::CMP: {
+ if (getenv("NOCMP")) break;
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+
+ // Look for (X86cmp (and $op, $imm), 0) and see if we can convert it to
+ // use a smaller encoding.
+ if (N0.getNode()->getOpcode() == ISD::AND && N0.getNode()->hasOneUse() &&
+ N0.getValueType() != MVT::i8 &&
+ X86::isZeroNode(N1)) {
+ ConstantSDNode *C = dyn_cast<ConstantSDNode>(N0.getNode()->getOperand(1));
+ if (!C) break;
+
+ // For example, convert "testl %eax, $8" to "testb %al, $8"
+ if ((C->getZExtValue() & ~UINT64_C(0xff)) == 0) {
+ SDValue Imm = CurDAG->getTargetConstant(C->getZExtValue(), MVT::i8);
+ SDValue Reg = N0.getNode()->getOperand(0);
+
+ // On x86-32, only the ABCD registers have 8-bit subregisters.
+ if (!Subtarget->is64Bit()) {
+ TargetRegisterClass *TRC = 0;
+ switch (N0.getValueType().getSimpleVT().SimpleTy) {
+ case MVT::i32: TRC = &X86::GR32_ABCDRegClass; break;
+ case MVT::i16: TRC = &X86::GR16_ABCDRegClass; break;
+ default: llvm_unreachable("Unsupported TEST operand type!");
+ }
+ SDValue RC = CurDAG->getTargetConstant(TRC->getID(), MVT::i32);
+ Reg = SDValue(CurDAG->getTargetNode(X86::COPY_TO_REGCLASS, dl,
+ Reg.getValueType(), Reg, RC), 0);
+ }
+
+ // Extract the l-register.
+ SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT, dl,
+ MVT::i8, Reg);
+
+ // Emit a testb.
+ return CurDAG->getTargetNode(X86::TEST8ri, dl, MVT::i32, Subreg, Imm);
+ }
+
+ // For example, "testl %eax, $2048" to "testb %ah, $8".
+ if ((C->getZExtValue() & ~UINT64_C(0xff00)) == 0) {
+ // Shift the immediate right by 8 bits.
+ SDValue ShiftedImm = CurDAG->getTargetConstant(C->getZExtValue() >> 8,
+ MVT::i8);
+ SDValue Reg = N0.getNode()->getOperand(0);
+
+ // Put the value in an ABCD register.
+ TargetRegisterClass *TRC = 0;
+ switch (N0.getValueType().getSimpleVT().SimpleTy) {
+ case MVT::i64: TRC = &X86::GR64_ABCDRegClass; break;
+ case MVT::i32: TRC = &X86::GR32_ABCDRegClass; break;
+ case MVT::i16: TRC = &X86::GR16_ABCDRegClass; break;
+ default: llvm_unreachable("Unsupported TEST operand type!");
+ }
+ SDValue RC = CurDAG->getTargetConstant(TRC->getID(), MVT::i32);
+ Reg = SDValue(CurDAG->getTargetNode(X86::COPY_TO_REGCLASS, dl,
+ Reg.getValueType(), Reg, RC), 0);
+
+ // Extract the h-register.
+ SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_8BIT_HI, dl,
+ MVT::i8, Reg);
+
+ // Emit a testb. No special NOREX tricks are needed since there's
+ // only one GPR operand!
+ return CurDAG->getTargetNode(X86::TEST8ri, dl, MVT::i32,
+ Subreg, ShiftedImm);
+ }
+
+ // For example, "testl %eax, $32776" to "testw %ax, $32776".
+ if ((C->getZExtValue() & ~UINT64_C(0xffff)) == 0 &&
+ N0.getValueType() != MVT::i16) {
+ SDValue Imm = CurDAG->getTargetConstant(C->getZExtValue(), MVT::i16);
+ SDValue Reg = N0.getNode()->getOperand(0);
+
+ // Extract the 16-bit subregister.
+ SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_16BIT, dl,
+ MVT::i16, Reg);
+
+ // Emit a testw.
+ return CurDAG->getTargetNode(X86::TEST16ri, dl, MVT::i32, Subreg, Imm);
+ }
+
+ // For example, "testq %rax, $268468232" to "testl %eax, $268468232".
+ if ((C->getZExtValue() & ~UINT64_C(0xffffffff)) == 0 &&
+ N0.getValueType() == MVT::i64) {
+ SDValue Imm = CurDAG->getTargetConstant(C->getZExtValue(), MVT::i32);
+ SDValue Reg = N0.getNode()->getOperand(0);
+
+ // Extract the 32-bit subregister.
+ SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::SUBREG_32BIT, dl,
+ MVT::i32, Reg);
+
+ // Emit a testl.
+ return CurDAG->getTargetNode(X86::TEST32ri, dl, MVT::i32, Subreg, Imm);
+ }
+ }
+ break;
+ }
+
case ISD::DECLARE: {
// Handle DECLARE nodes here because the second operand may have been
// wrapped in X86ISD::Wrapper.
Modified: llvm/trunk/test/CodeGen/X86/live-out-reg-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/live-out-reg-info.ll?rev=79439&r1=79438&r2=79439&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/live-out-reg-info.ll (original)
+++ llvm/trunk/test/CodeGen/X86/live-out-reg-info.ll Wed Aug 19 13:16:17 2009
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -march=x86-64 | grep testl
+; RUN: llvm-as < %s | llc -march=x86-64 | grep {testb \[$\]1,}
; Make sure dagcombine doesn't eliminate the comparison due
; to an off-by-one bug with ComputeMaskedBits information.
Added: llvm/trunk/test/CodeGen/X86/test-shrink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/test-shrink.ll?rev=79439&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/test-shrink.ll (added)
+++ llvm/trunk/test/CodeGen/X86/test-shrink.ll Wed Aug 19 13:16:17 2009
@@ -0,0 +1,158 @@
+; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s --check-prefix=CHECK-64
+; RUN: llvm-as < %s | llc -march=x86 | FileCheck %s --check-prefix=CHECK-32
+
+; CHECK-64: g64xh:
+; CHECK-64: testb $8, %ah
+; CHECK-64: ret
+; CHECK-32: g64xh:
+; CHECK-32: testb $8, %ah
+; CHECK-32: ret
+define void @g64xh(i64 inreg %x) nounwind {
+ %t = and i64 %x, 2048
+ %s = icmp eq i64 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g64xl:
+; CHECK-64: testb $8, %dil
+; CHECK-64: ret
+; CHECK-32: g64xl:
+; CHECK-32: testb $8, %al
+; CHECK-32: ret
+define void @g64xl(i64 inreg %x) nounwind {
+ %t = and i64 %x, 8
+ %s = icmp eq i64 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g32xh:
+; CHECK-64: testb $8, %ah
+; CHECK-64: ret
+; CHECK-32: g32xh:
+; CHECK-32: testb $8, %ah
+; CHECK-32: ret
+define void @g32xh(i32 inreg %x) nounwind {
+ %t = and i32 %x, 2048
+ %s = icmp eq i32 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g32xl:
+; CHECK-64: testb $8, %dil
+; CHECK-64: ret
+; CHECK-32: g32xl:
+; CHECK-32: testb $8, %al
+; CHECK-32: ret
+define void @g32xl(i32 inreg %x) nounwind {
+ %t = and i32 %x, 8
+ %s = icmp eq i32 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g16xh:
+; CHECK-64: testb $8, %ah
+; CHECK-64: ret
+; CHECK-32: g16xh:
+; CHECK-32: testb $8, %ah
+; CHECK-32: ret
+define void @g16xh(i16 inreg %x) nounwind {
+ %t = and i16 %x, 2048
+ %s = icmp eq i16 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g16xl:
+; CHECK-64: testb $8, %dil
+; CHECK-64: ret
+; CHECK-32: g16xl:
+; CHECK-32: testb $8, %al
+; CHECK-32: ret
+define void @g16xl(i16 inreg %x) nounwind {
+ %t = and i16 %x, 8
+ %s = icmp eq i16 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g64x16:
+; CHECK-64: testw $32896, %di
+; CHECK-64: ret
+; CHECK-32: g64x16:
+; CHECK-32: testw $32896, %ax
+; CHECK-32: ret
+define void @g64x16(i64 inreg %x) nounwind {
+ %t = and i64 %x, 32896
+ %s = icmp eq i64 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g32x16:
+; CHECK-64: testw $32896, %di
+; CHECK-64: ret
+; CHECK-32: g32x16:
+; CHECK-32: testw $32896, %ax
+; CHECK-32: ret
+define void @g32x16(i32 inreg %x) nounwind {
+ %t = and i32 %x, 32896
+ %s = icmp eq i32 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+; CHECK-64: g64x32:
+; CHECK-64: testl $268468352, %edi
+; CHECK-64: ret
+; CHECK-32: g64x32:
+; CHECK-32: testl $268468352, %eax
+; CHECK-32: ret
+define void @g64x32(i64 inreg %x) nounwind {
+ %t = and i64 %x, 268468352
+ %s = icmp eq i64 %t, 0
+ br i1 %s, label %yes, label %no
+
+yes:
+ call void @bar()
+ ret void
+no:
+ ret void
+}
+
+declare void @bar()
More information about the llvm-commits
mailing list