OSDN Git Service

Fix the expansion of umax and smax in the case where one or more of
authorDan Gohman <gohman@apple.com>
Tue, 14 Jul 2009 20:57:04 +0000 (20:57 +0000)
committerDan Gohman <gohman@apple.com>
Tue, 14 Jul 2009 20:57:04 +0000 (20:57 +0000)
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

lib/Analysis/ScalarEvolutionExpander.cpp
test/Transforms/IndVarSimplify/max-pointer.ll [new file with mode: 0644]

index ecfbc8e..20d6e20 100644 (file)
@@ -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 (file)
index 0000000..ba2b2fa
--- /dev/null
@@ -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
+}
+
+