aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-07-14 20:57:04 +0000
committerDan Gohman <gohman@apple.com>2009-07-14 20:57:04 +0000
commit94e647e5cd0d89015ac09112a3c055fa597b00d9 (patch)
tree6b7e3786656e5491bab100fe2ab41202520fbb5b
parenta338c248ae57d2d46dfdea45e2e6ae47daef72fa (diff)
downloadexternal_llvm-94e647e5cd0d89015ac09112a3c055fa597b00d9.zip
external_llvm-94e647e5cd0d89015ac09112a3c055fa597b00d9.tar.gz
external_llvm-94e647e5cd0d89015ac09112a3c055fa597b00d9.tar.bz2
Fix the expansion of umax and smax in the case where one or more of
the operands have pointer type, so that the resulting type matches the original SCEV type, and so that unnecessary ptrtoints are avoided in common cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75680 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp32
-rw-r--r--test/Transforms/IndVarSimplify/max-pointer.ll145
2 files changed, 171 insertions, 6 deletions
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index ecfbc8e..20d6e20 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -609,9 +609,15 @@ Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) {
}
Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) {
- const Type *Ty = SE.getEffectiveSCEVType(S->getType());
- Value *LHS = expandCodeFor(S->getOperand(0), Ty);
- for (unsigned i = 1; i < S->getNumOperands(); ++i) {
+ Value *LHS = expand(S->getOperand(S->getNumOperands()-1));
+ const Type *Ty = LHS->getType();
+ for (int i = S->getNumOperands()-2; i >= 0; --i) {
+ // In the case of mixed integer and pointer types, do the
+ // rest of the comparisons as integer.
+ if (S->getOperand(i)->getType() != Ty) {
+ Ty = SE.getEffectiveSCEVType(Ty);
+ LHS = InsertNoopCastOfTo(LHS, Ty);
+ }
Value *RHS = expandCodeFor(S->getOperand(i), Ty);
Value *ICmp = Builder.CreateICmpSGT(LHS, RHS, "tmp");
InsertedValues.insert(ICmp);
@@ -619,13 +625,23 @@ Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) {
InsertedValues.insert(Sel);
LHS = Sel;
}
+ // In the case of mixed integer and pointer types, cast the
+ // final result back to the pointer type.
+ if (LHS->getType() != S->getType())
+ LHS = InsertNoopCastOfTo(LHS, S->getType());
return LHS;
}
Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) {
- const Type *Ty = SE.getEffectiveSCEVType(S->getType());
- Value *LHS = expandCodeFor(S->getOperand(0), Ty);
- for (unsigned i = 1; i < S->getNumOperands(); ++i) {
+ Value *LHS = expand(S->getOperand(S->getNumOperands()-1));
+ const Type *Ty = LHS->getType();
+ for (int i = S->getNumOperands()-2; i >= 0; --i) {
+ // In the case of mixed integer and pointer types, do the
+ // rest of the comparisons as integer.
+ if (S->getOperand(i)->getType() != Ty) {
+ Ty = SE.getEffectiveSCEVType(Ty);
+ LHS = InsertNoopCastOfTo(LHS, Ty);
+ }
Value *RHS = expandCodeFor(S->getOperand(i), Ty);
Value *ICmp = Builder.CreateICmpUGT(LHS, RHS, "tmp");
InsertedValues.insert(ICmp);
@@ -633,6 +649,10 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) {
InsertedValues.insert(Sel);
LHS = Sel;
}
+ // In the case of mixed integer and pointer types, cast the
+ // final result back to the pointer type.
+ if (LHS->getType() != S->getType())
+ LHS = InsertNoopCastOfTo(LHS, S->getType());
return LHS;
}
diff --git a/test/Transforms/IndVarSimplify/max-pointer.ll b/test/Transforms/IndVarSimplify/max-pointer.ll
new file mode 100644
index 0000000..ba2b2fa
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/max-pointer.ll
@@ -0,0 +1,145 @@
+; RUN: llvm-as < %s | opt -indvars | llvm-dis > %t
+; RUN: grep {icmp ugt i8\\\*} %t | count 1
+; RUN: grep {icmp sgt i8\\\*} %t | count 1
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+
+ %struct.CKenCodeCodec = type <{ i8 }>
+
+define void @foo(i8* %str1Ptr, i8* %str2Ptr, i8* %inLastBytePtr) nounwind {
+entry:
+ %0 = icmp ult i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp ult i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+define void @bar(i8* %str1Ptr, i64 %s, i8* %inLastBytePtr) nounwind {
+entry:
+ %str2Ptr = inttoptr i64 %s to i8*
+ %0 = icmp ult i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp ult i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+define void @qux(i64 %t, i64 %s, i8* %inLastBytePtr) nounwind {
+entry:
+ %str1Ptr = inttoptr i64 %t to i8*
+ %str2Ptr = inttoptr i64 %s to i8*
+ %0 = icmp ult i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp ult i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+define void @vor(i64 %t, i8* %str2Ptr, i8* %inLastBytePtr) nounwind {
+entry:
+ %str1Ptr = inttoptr i64 %t to i8*
+ %0 = icmp ult i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp ult i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+define void @sfoo(i8* %str1Ptr, i8* %str2Ptr, i8* %inLastBytePtr) nounwind {
+entry:
+ %0 = icmp slt i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp slt i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+define void @sbar(i8* %str1Ptr, i64 %s, i8* %inLastBytePtr) nounwind {
+entry:
+ %str2Ptr = inttoptr i64 %s to i8*
+ %0 = icmp slt i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp slt i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+define void @squx(i64 %t, i64 %s, i8* %inLastBytePtr) nounwind {
+entry:
+ %str1Ptr = inttoptr i64 %t to i8*
+ %str2Ptr = inttoptr i64 %s to i8*
+ %0 = icmp slt i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp slt i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+define void @svor(i64 %t, i8* %str2Ptr, i8* %inLastBytePtr) nounwind {
+entry:
+ %str1Ptr = inttoptr i64 %t to i8*
+ %0 = icmp slt i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
+ %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb2, %entry
+ %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
+ %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
+ %2 = icmp slt i8* %1, %inLastBytePtr ; <i1> [#uses=0]
+ br i1 false, label %bb2, label %return
+
+return: ; preds = %bb2
+ ret void
+}
+
+