[llvm-commits] CAST patch: Part #2: .ll/.bc readers + Analysis

Chris Lattner clattner at apple.com
Mon Nov 20 14:07:19 PST 2006


On Nov 18, 2006, at 11:24 AM, Reid Spencer wrote:

> Chris,
>
> Here's the CAST patch. This passes 100% of llvm/test and llvm-test.  
> The
> order of the files in the patch has been set up for logical review.  
> Some
> of this you've already seen, but its changed so much that those things
> should probably be reviewed again.

The two occurrences of:

+    if ($1.obsolete && ($4->get() == Type::BoolTy)) {
+      // The previous definition of cast to bool was a compare  
against zero.
+      // We have to retain that semantic so we do it here.
+      $$ = new SetCondInst(Instruction::SetEQ, $2,
+                             Constant::getNullValue($2->getType()));
+      $1.obsolete = false;

are wrong, this should be SetNE X, nullvalue.  You got this right  
once in the bc reader, but this one is wrong:

@@ -1585,13 +1660,23 @@ inline unsigned BytecodeReader::upgradeC
        Opcode = Instruction::SetGT;
        break;
      case 26: // GetElementPtr
        Opcode = Instruction::GetElementPtr;
        break;
-    case 28: // Cast
-      Opcode = Instruction::Cast;
+    case 28: { // Cast
+      const Type *Ty = getType(TypeID);
+      if (Ty == Type::BoolTy) {
+        // The previous definition of cast to bool was a compare  
against zero.
+        // We have to retain that semantic so we do it here.
+        Opcode = Instruction::SetEQ;
+        return ConstantExpr::get(Instruction::SetEQ, ArgVec[0],
+                             Constant::getNullValue(ArgVec[0]- 
 >getType()));
+      } else {
+        Opcode = CastInst::getCastOpcode(ArgVec[0], Ty);
+      }
        break;
+    }
      case 30: // Shl
        Opcode = Instruction::Shl;
        break;
      case 31: // Shr
        if (ArgVec[0]->getType()->isSigned())


diff -t -d -u -p -5 -r1.38 Reader.h
--- lib/Bytecode/Reader/Reader.h	14 Nov 2006 04:47:22 -0000	1.38
+++ lib/Bytecode/Reader/Reader.h	18 Nov 2006 19:22:09 -0000
@@ -300,10 +301,12 @@ private:
    // In version 7, the Shr, Cast and Setcc instructions changed to  
their
    // signed counterparts. This flag will be true if these  
instructions are
    // signless (version 6 and prior).
    bool hasSignlessShrCastSetcc;

+  bool hasSingleCast;
+

This needs a comment.




@@ -1345,29 +1343,39 @@ SCEVHandle ScalarEvolutionsImpl::createN
  ///
  SCEVHandle ScalarEvolutionsImpl::createNodeForCast(CastInst *CI) {
    const Type *SrcTy = CI->getOperand(0)->getType();
    const Type *DestTy = CI->getType();

-  // If this is a noop cast (ie, conversion from int to uint),  
ignore it.
-  if (SrcTy->isLosslesslyConvertibleTo(DestTy))
+  // If this is a noop cast (eg, conversion from int to uint),  
ignore it.
+  // NOTE: We should be passing in TargetData->getIntPtrType() to  
isNoopCast
+  // here for more accurate Int->Ptr and Ptr->Int no-op detection.  
Using
+  // ULongTy pessimizes this check for 32-bit platforms.
+  if (CI->isNoopCast(Type::ULongTy))
      return getSCEV(CI->getOperand(0));

I believe that this is subtly wrong.  The SCEV code doesn't really  
handle pointers correctly, and the old isLosslesslyConvertibleTo  
method would not return true for int<->ptr casts.  Please change this  
to check for isa<BitCast>, which is equivalent to the old code.   
Please also remove the NOTE comment.


+  // The cast operations can deal with bool and other types here. We  
only want
+  // integer casts so check that condition.
    if (SrcTy->isInteger() && DestTy->isInteger()) {
+    switch (CI->getOpcode()) {
+    case Instruction::Trunc:
+      return SCEVTruncateExpr::get(getSCEV(CI->getOperand(0)),
+          DestTy->getUnsignedVersion());
+    case Instruction::ZExt:
+      return SCEVZeroExtendExpr::get(getSCEV(CI->getOperand(0)),
+          DestTy->getUnsignedVersion());
+    case Instruction::BitCast:
+        return SCEVZeroExtendExpr::get(getSCEV(CI->getOperand(0)),
+            DestTy->getUnsignedVersion());
+      break;
+    default:
+      // If this is a sign or zero extending cast and we can prove  
that the
+      // value will never overflow, we could do similar  
transformations. But,
+      // we can't handle this yet.
+      break;
+    }

The Instruction::BitCast case has already been handled by the  
isa<BitCast> check above, plz remove it.  Overall, I think it would  
be cleaner to split createNodeForCast into createNodeForBitCast,  
createNodeForZext and createNodeForTrunc than to try to handle these  
three cases in one method.

+++ lib/Analysis/ValueNumbering.cpp	18 Nov 2006 19:22:11 -0000
@@ -110,12 +110,16 @@ void BVNImpl::visitCastInst(CastInst &CI
    Function *F = I.getParent()->getParent();

    for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
         UI != UE; ++UI)
      if (CastInst *Other = dyn_cast<CastInst>(*UI))
-      // Check that the types are the same, since this code handles  
casts...
-      if (Other->getType() == I.getType() &&
+      // Check that the opcode is the same
+      if (Other->getOpcode() == Instruction::CastOps(I.getOpcode()) &&
+          // Check that the destination types are the same
+          Other->getType() == I.getType() &&
+          // Check that the source types are the same
+          CI.getOperand(0)->getType() == Other->getOperand(0)- 
 >getType() &&
            // Is it embedded in the same function?  (This could be  
false if LHS
            // is a constant or global!)
            Other->getParent()->getParent() == F &&
            // Check to see if this new cast is not I.
            Other != &I) {

There is no need to check this:

+          // Check that the source types are the same
+          CI.getOperand(0)->getType() == Other->getOperand(0)- 
 >getType() &&

Since you know that CI.getOperand(0) == Other->getOperand(0) already.



--- lib/Analysis/IPA/GlobalsModRef.cpp	1 Oct 2006 22:46:33 -0000	1.23
+++ lib/Analysis/IPA/GlobalsModRef.cpp	18 Nov 2006 19:22:12 -0000
@@ -165,14 +165,17 @@ static Value *getUnderlyingObject(Value
    // If we are at some type of object... return it.
    if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) return GV;

    // Traverse through different addressing mechanisms.
    if (Instruction *I = dyn_cast<Instruction>(V)) {
-    if (isa<CastInst>(I) || isa<GetElementPtrInst>(I))
+    if (isa<BitCastInst>(I) ||
+        isa<IntToPtrInst>(I) ||
+        isa<GetElementPtrInst>(I))
        return getUnderlyingObject(I->getOperand(0));
    } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
-    if (CE->getOpcode() == Instruction::Cast ||
+    if (CE->getOpcode() == Instruction::BitCast ||
+        CE->getOpcode() == Instruction::IntToPtr ||
          CE->getOpcode() == Instruction::GetElementPtr)
        return getUnderlyingObject(CE->getOperand(0));
    }

    // Othewise, we don't know what this is, return it as the base  
pointer.


You don't want to include IntToPtr in either of these.


@@ -250,12 +253,11 @@ bool GlobalsModRef::AnalyzeUsesOfPointer
        // Make sure that this is just the function being called, not  
that it is
        // passing into the function.
        for (unsigned i = 3, e = II->getNumOperands(); i != e; ++i)
          if (II->getOperand(i) == V) return true;
      } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(*UI)) {
-      if (CE->getOpcode() == Instruction::GetElementPtr ||
-          CE->getOpcode() == Instruction::Cast) {
+      if (CE->getOpcode() == Instruction::GetElementPtr || CE->isCast 
()) {
          if (AnalyzeUsesOfPointer(CE, Readers, Writers))
            return true;

This should just allow GEP and BitCast, not any Cast.

-Chris








-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20061120/aa97b81c/attachment.html>


More information about the llvm-commits mailing list