optimize a common idiom generated by clang for bitfield access, PR2638.
authorChris Lattner <sabre@nondot.org>
Wed, 6 Aug 2008 07:35:52 +0000 (07:35 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 6 Aug 2008 07:35:52 +0000 (07:35 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54408 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 44083bc2d00105c854a1f6484ba57c45a0f46782..3a74c7f73d0ff6db1492d0a38aaf8b2103fc88dd 100644 (file)
@@ -7666,7 +7666,37 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
         return new TruncInst(Op, CI.getType(), "tmp");
     }
   }
-      
+
+  // If the input is a shl/ashr pair of a same constant, then this is a sign
+  // extension from a smaller value.  If we could trust arbitrary bitwidth
+  // integers, we could turn this into a truncate to the smaller bit and then
+  // use a sext for the whole extension.  Since we don't, look deeper and check
+  // for a truncate.  If the source and dest are the same type, eliminate the
+  // trunc and extend and just do shifts.  For example, turn:
+  //   %a = trunc i32 %i to i8
+  //   %b = shl i8 %a, 6
+  //   %c = ashr i8 %b, 6
+  //   %d = sext i8 %c to i32
+  // into:
+  //   %a = shl i32 %i, 30
+  //   %d = ashr i32 %a, 30
+  Value *A = 0;
+  ConstantInt *BA = 0, *CA = 0;
+  if (match(Src, m_AShr(m_Shl(m_Value(A), m_ConstantInt(BA)),
+                        m_ConstantInt(CA))) &&
+      BA == CA && isa<TruncInst>(A)) {
+    Value *I = cast<TruncInst>(A)->getOperand(0);
+    if (I->getType() == CI.getType()) {
+      unsigned MidSize = Src->getType()->getPrimitiveSizeInBits();
+      unsigned SrcDstSize = CI.getType()->getPrimitiveSizeInBits();
+      unsigned ShAmt = CA->getZExtValue()+SrcDstSize-MidSize;
+      Constant *ShAmtV = ConstantInt::get(CI.getType(), ShAmt);
+      I = InsertNewInstBefore(BinaryOperator::CreateShl(I, ShAmtV,
+                                                        CI.getName()), CI);
+      return BinaryOperator::CreateAShr(I, ShAmtV);
+    }
+  }
+  
   return 0;
 }
 
index 69850025aca289ef5a20621b2100035aee260227..58749666ea1b50b435432f344814b40ef366f943 100644 (file)
@@ -63,3 +63,13 @@ F:
        ret i16 %W
 }
 
+; PR2638
+define i32 @test2(i32 %i) nounwind  {
+entry:
+        %tmp12 = trunc i32 %i to i8             ; <i8> [#uses=1]
+        %tmp16 = shl i8 %tmp12, 6               ; <i8> [#uses=1]
+        %a = ashr i8 %tmp16, 6            ; <i8> [#uses=1]
+        %b = sext i8 %a to i32            ; <i32> [#uses=1]
+        ret i32 %b
+}
+