[llvm-commits] [PATCH] Patch (WIP) to custom-lower 64-bit relational comparisons on x86-32
Eli Friedman
eli.friedman at gmail.com
Wed Feb 16 16:25:14 PST 2011
Example of what the attached patch does (x86-32):
C code:
int foo();
int bar(long long x, long long y) { if (x < y) foo(); }
Current generated code:
subl $12, %esp
movl 16(%esp), %eax
movl 20(%esp), %ecx
cmpl 24(%esp), %eax
setae %al
cmpl 28(%esp), %ecx
setge %cl
je .LBB0_2
movb %cl, %al
.LBB0_2:
testb %al, %al
jne .LBB0_4
calll foo
.LBB0_4:
addl $12, %esp
ret
New generated code:
subl $12, %esp
movl 16(%esp), %eax
movl 20(%esp), %ecx
subl 24(%esp), %eax
sbbl 28(%esp), %ecx
jge .LBB0_2
calll foo
.LBB0_2:
addl $12, %esp
ret
I initially wrote this patch a couple years ago, but the backend
choked on it before some recent changes.
The reason this works is that on x86, comparisons are fundamentally
just subtraction. So to do a wide comparison, all that is necessary
is to split the subtraction, and use the flag results of the top half.
A bit of trickiness is required because the ZF flag isn't set in a
useful way, but that's straightforward to solve: don't lower equality
comparisons with this method and commute other comparisons that look
at the ZF flag.
I'm mainly looking for feedback as to whether this seems like
generally a good idea... I haven't seen any compiler use this
particular implementation of relational comparisons.
-Eli
-------------- next part --------------
Index: X86/X86ISelLowering.cpp
===================================================================
--- X86/X86ISelLowering.cpp (revision 125651)
+++ X86/X86ISelLowering.cpp (working copy)
@@ -446,6 +446,7 @@
setOperationAction(ISD::SETCC , MVT::i8 , Custom);
setOperationAction(ISD::SETCC , MVT::i16 , Custom);
setOperationAction(ISD::SETCC , MVT::i32 , Custom);
+ setOperationAction(ISD::SETCC , MVT::i64 , Custom);
setOperationAction(ISD::SETCC , MVT::f32 , Custom);
setOperationAction(ISD::SETCC , MVT::f64 , Custom);
setOperationAction(ISD::SETCC , MVT::f80 , Custom);
@@ -7402,6 +7403,38 @@
if (X86CC == X86::COND_INVALID)
return SDValue();
+ if (!Subtarget->is64Bit() && Op0.getValueType() == MVT::i64) {
+ if (X86CC == X86::COND_E || X86CC == X86::COND_NE)
+ return SDValue();
+ if (X86CC == X86::COND_A) {
+ X86CC = X86::COND_B;
+ std::swap(Op0, Op1);
+ } else if (X86CC == X86::COND_BE) {
+ X86CC = X86::COND_AE;
+ std::swap(Op0, Op1);
+ } else if (X86CC == X86::COND_G) {
+ X86CC = X86::COND_L;
+ std::swap(Op0, Op1);
+ } else if (X86CC == X86::COND_LE) {
+ X86CC = X86::COND_GE;
+ std::swap(Op0, Op1);
+ }
+ SDValue Op0Low = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Op0, DAG.getIntPtrConstant(0));
+ SDValue Op1Low = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Op1, DAG.getIntPtrConstant(0));
+ SDValue Op0High = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Op0, DAG.getIntPtrConstant(1));
+ SDValue Op1High = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
+ Op1, DAG.getIntPtrConstant(1));
+ SDValue res1, res2;
+ SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i32);
+ res1 = SDValue(DAG.getNode(X86ISD::SUB, dl, VTList, Op0Low, Op1Low).getNode(), 1);
+ res2 = SDValue(DAG.getNode(X86ISD::SBB, dl, VTList, Op0High, Op1High, res1).getNode(), 1);
+ return DAG.getNode(X86ISD::SETCC, dl, MVT::i8,
+ DAG.getConstant(X86CC, MVT::i8), res2);
+ }
+
SDValue EFLAGS = EmitCmp(Op0, Op1, X86CC, DAG);
return DAG.getNode(X86ISD::SETCC, dl, MVT::i8,
DAG.getConstant(X86CC, MVT::i8), EFLAGS);
More information about the llvm-commits
mailing list