Port SelectionDAG's ComputeNumSignBits-using code to instcombine,
authorDan Gohman <gohman@apple.com>
Tue, 20 May 2008 21:01:12 +0000 (21:01 +0000)
committerDan Gohman <gohman@apple.com>
Tue, 20 May 2008 21:01:12 +0000 (21:01 +0000)
now that instcombine also has ComputeNumSignBits.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51350 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/sext-misc.ll

index b8b64951668372ea4a0ae63a3dcdb8ea3b30386b..c35bc49e512c026bc6e75dd17bcff00b31adb5b7 100644 (file)
@@ -2085,7 +2085,7 @@ unsigned InstCombiner::ComputeNumSignBits(Value *V, unsigned Depth) const{
     
   case Instruction::AShr:
     Tmp = ComputeNumSignBits(U->getOperand(0), Depth+1);
-    // SRA X, C   -> adds C sign bits.
+    // ashr X, C   -> adds C sign bits.
     if (ConstantInt *C = dyn_cast<ConstantInt>(U->getOperand(1))) {
       Tmp += C->getZExtValue();
       if (Tmp > TyBits) Tmp = TyBits;
@@ -8195,6 +8195,33 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
       }
     }
   }
+
+  // See if the value being truncated is already sign extended.  If so, just
+  // eliminate the trunc/sext pair.
+  if (getOpcode(Src) == Instruction::Trunc) {
+    Value *Op = cast<User>(Src)->getOperand(0);
+    unsigned OpBits   = cast<IntegerType>(Op->getType())->getBitWidth();
+    unsigned MidBits  = cast<IntegerType>(Src->getType())->getBitWidth();
+    unsigned DestBits = cast<IntegerType>(CI.getType())->getBitWidth();
+    unsigned NumSignBits = ComputeNumSignBits(Op);
+
+    if (OpBits == DestBits) {
+      // Op is i32, Mid is i8, and Dest is i32.  If Op has more than 24 sign
+      // bits, it is already ready.
+      if (NumSignBits > DestBits-MidBits)
+        return ReplaceInstUsesWith(CI, Op);
+    } else if (OpBits < DestBits) {
+      // Op is i32, Mid is i8, and Dest is i64.  If Op has more than 24 sign
+      // bits, just sext from i32.
+      if (NumSignBits > OpBits-MidBits)
+        return new SExtInst(Op, CI.getType(), "tmp");
+    } else {
+      // Op is i64, Mid is i8, and Dest is i32.  If Op has more than 56 sign
+      // bits, just truncate to i32.
+      if (NumSignBits > OpBits-MidBits)
+        return new TruncInst(Op, CI.getType(), "tmp");
+    }
+  }
       
   return 0;
 }
index da69e85ff5f3f1ba93b3f137a58b820787f32539..d49c63cca6e72dff0a3259b397c1c610f6c99c16 100644 (file)
@@ -43,3 +43,10 @@ define i64 @voo(i32 %x) {
   %s = sext i32 %u to i64
   ret i64 %s
 }
+define i32 @woo(i8 %a, i32 %f, i1 %p, i32* %z) {
+  %d = ashr i32 %f, 24
+  %e = select i1 %p, i32 %d, i32 0
+  %s = trunc i32 %e to i16
+  %n = sext i16 %s to i32
+  ret i32 %n
+}