[llvm-commits] [llvm] r71446 - in /llvm/trunk: lib/Target/X86/X86ISelDAGToDAG.cpp lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/lea-neg.ll
Dan Gohman
gohman at apple.com
Mon May 11 11:02:54 PDT 2009
Author: djg
Date: Mon May 11 13:02:53 2009
New Revision: 71446
URL: http://llvm.org/viewvc/llvm-project?rev=71446&view=rev
Log:
Convert a subtract into a negate and an add when it helps x86
address folding.
Added:
llvm/trunk/test/CodeGen/X86/lea-neg.ll
Modified:
llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
llvm/trunk/lib/Target/X86/X86InstrInfo.td
Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=71446&r1=71445&r2=71446&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Mon May 11 13:02:53 2009
@@ -868,6 +868,76 @@
}
break;
+ case ISD::SUB: {
+ // Given A-B, if A can be completely folded into the address and
+ // the index field with the index field unused, use -B as the index.
+ // This is a win if a has multiple parts that can be folded into
+ // the address. Also, this saves a mov if the base register has
+ // other uses, since it avoids a two-address sub instruction, however
+ // it costs an additional mov if the index register has other uses.
+
+ // Test if the LHS of the sub can be folded.
+ X86ISelAddressMode Backup = AM;
+ if (MatchAddress(N.getNode()->getOperand(0), AM, Depth+1)) {
+ AM = Backup;
+ break;
+ }
+ // Test if the index field is free for use.
+ if (AM.IndexReg.getNode() || AM.isRIPRel) {
+ AM = Backup;
+ break;
+ }
+ int Cost = 0;
+ SDValue RHS = N.getNode()->getOperand(1);
+ // If the RHS involves a register with multiple uses, this
+ // transformation incurs an extra mov, due to the neg instruction
+ // clobbering its operand.
+ if (!RHS.getNode()->hasOneUse() ||
+ RHS.getNode()->getOpcode() == ISD::CopyFromReg ||
+ RHS.getNode()->getOpcode() == ISD::TRUNCATE ||
+ RHS.getNode()->getOpcode() == ISD::ANY_EXTEND ||
+ (RHS.getNode()->getOpcode() == ISD::ZERO_EXTEND &&
+ RHS.getNode()->getOperand(0).getValueType() == MVT::i32))
+ ++Cost;
+ // If the base is a register with multiple uses, this
+ // transformation may save a mov.
+ if ((AM.BaseType == X86ISelAddressMode::RegBase &&
+ AM.Base.Reg.getNode() &&
+ !AM.Base.Reg.getNode()->hasOneUse()) ||
+ AM.BaseType == X86ISelAddressMode::FrameIndexBase)
+ --Cost;
+ // If the folded LHS was interesting, this transformation saves
+ // address arithmetic.
+ if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) +
+ ((AM.Disp != 0) && (Backup.Disp == 0)) +
+ (AM.Segment.getNode() && !Backup.Segment.getNode()) >= 2)
+ --Cost;
+ // If it doesn't look like it may be an overall win, don't do it.
+ if (Cost >= 0) {
+ AM = Backup;
+ break;
+ }
+
+ // Ok, the transformation is legal and appears profitable. Go for it.
+ SDValue Zero = CurDAG->getConstant(0, N.getValueType());
+ SDValue Neg = CurDAG->getNode(ISD::SUB, dl, N.getValueType(), Zero, RHS);
+ AM.IndexReg = Neg;
+ AM.Scale = 1;
+
+ // Insert the new nodes into the topological ordering.
+ if (Zero.getNode()->getNodeId() == -1 ||
+ Zero.getNode()->getNodeId() > N.getNode()->getNodeId()) {
+ CurDAG->RepositionNode(N.getNode(), Zero.getNode());
+ Zero.getNode()->setNodeId(N.getNode()->getNodeId());
+ }
+ if (Neg.getNode()->getNodeId() == -1 ||
+ Neg.getNode()->getNodeId() > N.getNode()->getNodeId()) {
+ CurDAG->RepositionNode(N.getNode(), Neg.getNode());
+ Neg.getNode()->setNodeId(N.getNode()->getNodeId());
+ }
+ return false;
+ }
+
case ISD::ADD: {
X86ISelAddressMode Backup = AM;
if (!MatchAddress(N.getNode()->getOperand(0), AM, Depth+1) &&
Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=71446&r1=71445&r2=71446&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Mon May 11 13:02:53 2009
@@ -217,7 +217,7 @@
// Define X86 specific addressing mode.
def addr : ComplexPattern<iPTR, 5, "SelectAddr", [], []>;
def lea32addr : ComplexPattern<i32, 4, "SelectLEAAddr",
- [add, mul, shl, or, frameindex], []>;
+ [add, sub, mul, shl, or, frameindex], []>;
//===----------------------------------------------------------------------===//
// X86 Instruction Predicate Definitions.
Added: llvm/trunk/test/CodeGen/X86/lea-neg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-neg.ll?rev=71446&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/lea-neg.ll (added)
+++ llvm/trunk/test/CodeGen/X86/lea-neg.ll Mon May 11 13:02:53 2009
@@ -0,0 +1,25 @@
+; RUN: llvm-as < %s | llc -march=x86-64 > %t
+; RUN: grep negl %t | count 1
+; RUN: not grep sub %t
+; RUN: grep mov %t | count 1
+; RUN: grep {leal -4(} %t | count 1
+
+; ISel the add of -4 with a neg and use an lea for the rest of the
+; arithemtic.
+
+define i32 @test(i32 %x_offs) nounwind readnone {
+entry:
+ %t0 = icmp sgt i32 %x_offs, 4 ; <i1> [#uses=1]
+ br i1 %t0, label %bb.nph, label %bb2
+
+bb.nph: ; preds = %entry
+ %tmp = add i32 %x_offs, -5 ; <i32> [#uses=1]
+ %tmp6 = lshr i32 %tmp, 2 ; <i32> [#uses=1]
+ %tmp7 = mul i32 %tmp6, -4 ; <i32> [#uses=1]
+ %tmp8 = add i32 %tmp7, %x_offs ; <i32> [#uses=1]
+ %tmp9 = add i32 %tmp8, -4 ; <i32> [#uses=1]
+ ret i32 %tmp9
+
+bb2: ; preds = %entry
+ ret i32 %x_offs
+}
More information about the llvm-commits
mailing list