diff options
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 41 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/cast.ll | 46 | 
2 files changed, 60 insertions, 27 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index b0d017e0620..13f60716f2e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -919,34 +919,25 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {      if (NumBitsSExt == 0)        return 0; +    // Okay, we can transform this!  Insert the new expression now. +    DEBUG(dbgs() << "ICE: EvaluateInDifferentType converting expression type" +          " to avoid sign extend: " << CI); +    Value *Res = EvaluateInDifferentType(Src, DestTy, true); +    assert(Res->getType() == DestTy); +      uint32_t SrcBitSize = SrcTy->getScalarSizeInBits();      uint32_t DestBitSize = DestTy->getScalarSizeInBits(); + +    // If the high bits are already filled with sign bit, just replace this +    // cast with the result. +    if (NumBitsSExt > DestBitSize - SrcBitSize || +        ComputeNumSignBits(Res) > DestBitSize - SrcBitSize) +      return ReplaceInstUsesWith(CI, Res); -    // Because this is a sign extension, we can always transform it by inserting -    // two new shifts (to do the extension).  However, this is only profitable -    // if we've eliminated two or more casts from the input.  If we know the -    // result will be sign-extended enough to not require these shifts, we can -    // always do the transformation. -    if (NumCastsRemoved >= 2 || -        NumBitsSExt > DestBitSize-SrcBitSize) { -       -      // Okay, we can transform this!  Insert the new expression now. -      DEBUG(dbgs() << "ICE: EvaluateInDifferentType converting expression type" -            " to avoid sign extend: " << CI); -      Value *Res = EvaluateInDifferentType(Src, DestTy, true); -      assert(Res->getType() == DestTy); -       -      // If the high bits are already filled with sign bit, just replace this -      // cast with the result. -      if (NumBitsSExt > DestBitSize - SrcBitSize || -          ComputeNumSignBits(Res) > DestBitSize - SrcBitSize) -        return ReplaceInstUsesWith(CI, Res); -       -      // We need to emit a shl + ashr to do the sign extend. -      Value *ShAmt = ConstantInt::get(DestTy, DestBitSize-SrcBitSize); -      return BinaryOperator::CreateAShr(Builder->CreateShl(Res, ShAmt, "sext"), -                                        ShAmt); -    } +    // We need to emit a shl + ashr to do the sign extend. +    Value *ShAmt = ConstantInt::get(DestTy, DestBitSize-SrcBitSize); +    return BinaryOperator::CreateAShr(Builder->CreateShl(Res, ShAmt, "sext"), +                                      ShAmt);    }    // If the input is a shl/ashr pair of a same constant, then this is a sign diff --git a/llvm/test/Transforms/InstCombine/cast.ll b/llvm/test/Transforms/InstCombine/cast.ll index de7f8c11f26..4f0475ac59d 100644 --- a/llvm/test/Transforms/InstCombine/cast.ll +++ b/llvm/test/Transforms/InstCombine/cast.ll @@ -185,8 +185,8 @@ define i32 @test22(i32 %X) {          %c2 = sext i8 %c1 to i32                ; <i32> [#uses=1]          %RV = shl i32 %c2, 24           ; <i32> [#uses=1]          ret i32 %RV -; CHECK: %RV = shl i32 %X, 24 -; CHECK: ret i32 %RV +; CHECK: shl i32 %X, 24 +; CHECK-NEXT: ret i32  }  define i32 @test23(i32 %X) { @@ -457,3 +457,45 @@ define i64 @test48(i8 %A, i8 %a) {  ; CHECK-NEXT: ret i64 %D  } +define i64 @test49(i64 %A) { + %B = trunc i64 %A to i32 + %C = or i32 %B, 1 + %D = sext i32 %C to i64  + ret i64 %D +; CHECK: @test49 +; CHECK-NEXT: %C = shl i64 %A, 32 +; CHECK-NEXT: ashr i64 %C, 32 +; CHECK-NEXT: %D = or i64 {{.*}}, 1 +; CHECK-NEXT: ret i64 %D +} + +define i64 @test50(i64 %A) { +  %a = lshr i64 %A, 2 +  %B = trunc i64 %a to i32 +  %D = add i32 %B, -1 +  %E = sext i32 %D to i64 +  ret i64 %E +; CHECK: @test50 +; CHECK-NEXT: shl i64 %A, 30 +; CHECK-NEXT: add i64 {{.*}}, -4294967296 +; CHECK-NEXT: %E = ashr i64 {{.*}}, 32 +; CHECK-NEXT: ret i64 %E +} + +define i64 @test51(i64 %A, i1 %cond) { +  %B = trunc i64 %A to i32 +  %C = and i32 %B, -2 +  %D = or i32 %B, 1 +  %E = select i1 %cond, i32 %C, i32 %D +  %F = sext i32 %E to i64 +  ret i64 %F +; CHECK: @test51 +; CHECK-NEXT: %C = and i64 %A, 4294967294 +; CHECK-NEXT: %D = or i64 %A, 1 +; CHECK-NEXT: %E = select i1 %cond, i64 %C, i64 %D +; CHECK-NEXT: %sext = shl i64 %E, 32 +; CHECK-NEXT: %F = ashr i64 %sext, 32 +; CHECK-NEXT: ret i64 %F + +} +  | 

