aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-03-26 14:45:54 -0700
committerAlon Zakai <alonzakai@gmail.com>2014-03-26 14:45:54 -0700
commit9901f6970fb393d63b606624b1fce828ada7c7e3 (patch)
tree8505b12b4903e8e2550d5e150690cfeb1a6b91ae
parentf80db17a78b7194761a717435c0ff015c7d92247 (diff)
optimize x < 0 and generalize it to non-i64 values too
-rw-r--r--lib/Target/JSBackend/ExpandI64.cpp9
-rw-r--r--test/CodeGen/JS/expand-i64.ll15
2 files changed, 24 insertions, 0 deletions
diff --git a/lib/Target/JSBackend/ExpandI64.cpp b/lib/Target/JSBackend/ExpandI64.cpp
index 1fbf0ddebd..5a5a39ade2 100644
--- a/lib/Target/JSBackend/ExpandI64.cpp
+++ b/lib/Target/JSBackend/ExpandI64.cpp
@@ -646,6 +646,15 @@ bool ExpandI64::splitInst(Instruction *I) {
case ICmpInst::ICMP_SLE:
case ICmpInst::ICMP_UGE:
case ICmpInst::ICMP_SGE: {
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ if (CI->getZExtValue() == 0 && Pred == ICmpInst::ICMP_SLT) {
+ // strict < 0 is easy to do, even on non-i64, just the sign bit matters
+ Instruction *NewInst = new ICmpInst(I, ICmpInst::ICMP_SLT, LeftChunks[LeftChunks.size()-1], Zero);
+ CopyDebug(NewInst, I);
+ I->replaceAllUsesWith(NewInst);
+ return true;
+ }
+ }
assert(I->getOperand(0)->getType() == i64);
Instruction *A, *B, *C, *D, *Final;
ICmpInst::Predicate StrictPred = Pred;
diff --git a/test/CodeGen/JS/expand-i64.ll b/test/CodeGen/JS/expand-i64.ll
index a8a1875fa4..d667548abf 100644
--- a/test/CodeGen/JS/expand-i64.ll
+++ b/test/CodeGen/JS/expand-i64.ll
@@ -312,3 +312,18 @@ dead:
store i64 %s, i64* %p
ret void
}
+
+; CHECK: define i1 @slt_zero(i32 %a) {
+; CHECK: %1 = icmp slt i32 %a, 0
+; CHECK: %2 = sext i1 %1 to i32
+; CHECK: %3 = sext i1 %1 to i32
+; CHECK: %4 = sext i1 %1 to i32
+; CHECK: %5 = icmp slt i32 %4, 0
+; CHECK: ret i1 %5
+; CHECK: }
+define i1 @slt_zero(i32 %a) {
+ %b = sext i32 %a to i128
+ %c = icmp slt i128 %b, 0
+ ret i1 %c
+}
+