Value *Src = CI.getOperand(0);
- // If this is a cast of a cast
- if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
- // If this is a TRUNC followed by a ZEXT then we are dealing with integral
- // types and if the sizes are just right we can convert this into a logical
- // 'and' which will be much cheaper than the pair of casts.
- if (isa<TruncInst>(CSrc)) {
- // Get the sizes of the types involved
- Value *A = CSrc->getOperand(0);
- uint32_t SrcSize = A->getType()->getPrimitiveSizeInBits();
- uint32_t MidSize = CSrc->getType()->getPrimitiveSizeInBits();
- uint32_t DstSize = CI.getType()->getPrimitiveSizeInBits();
- // If we're actually extending zero bits and the trunc is a no-op
- if (MidSize < DstSize && SrcSize == DstSize) {
- // Replace both of the casts with an And of the type mask.
- APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
- Constant *AndConst = ConstantInt::get(AndValue);
- Instruction *And =
- BinaryOperator::CreateAnd(CSrc->getOperand(0), AndConst);
- // Unfortunately, if the type changed, we need to cast it back.
- if (And->getType() != CI.getType()) {
- And->setName(CSrc->getName()+".mask");
- InsertNewInstBefore(And, CI);
- And = CastInst::CreateIntegerCast(And, CI.getType(), false/*ZExt*/);
- }
- return And;
- }
+ // If this is a TRUNC followed by a ZEXT then we are dealing with integral
+ // types and if the sizes are just right we can convert this into a logical
+ // 'and' which will be much cheaper than the pair of casts.
+ if (TruncInst *CSrc = dyn_cast<TruncInst>(Src)) { // A->B->C cast
+ // Get the sizes of the types involved. We know that the intermediate type
+ // will be smaller than A or C, but don't know the relation between A and C.
+ Value *A = CSrc->getOperand(0);
+ unsigned SrcSize = A->getType()->getPrimitiveSizeInBits();
+ unsigned MidSize = CSrc->getType()->getPrimitiveSizeInBits();
+ unsigned DstSize = CI.getType()->getPrimitiveSizeInBits();
+ // If we're actually extending zero bits, then if
+ // SrcSize < DstSize: zext(a & mask)
+ // SrcSize == DstSize: a & mask
+ // SrcSize > DstSize: trunc(a) & mask
+ if (SrcSize < DstSize) {
+ APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
+ Constant *AndConst = ConstantInt::get(AndValue);
+ Instruction *And =
+ BinaryOperator::CreateAnd(A, AndConst, CSrc->getName()+".mask");
+ InsertNewInstBefore(And, CI);
+ return new ZExtInst(And, CI.getType());
+ } else if (SrcSize == DstSize) {
+ APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
+ return BinaryOperator::CreateAnd(A, ConstantInt::get(AndValue));
+ } else if (SrcSize > DstSize) {
+ Instruction *Trunc = new TruncInst(A, CI.getType(), "tmp");
+ InsertNewInstBefore(Trunc, CI);
+ APInt AndValue(APInt::getLowBitsSet(DstSize, MidSize));
+ return BinaryOperator::CreateAnd(Trunc, ConstantInt::get(AndValue));
}
}
ret i64 %c2
}
+; PR3599
+define i32 @test2(i64 %tmp) nounwind readnone {
+entry:
+ %tmp5 = trunc i64 %tmp to i8 ; <i8> [#uses=1]
+ %tmp7 = lshr i64 %tmp, 8 ; <i64> [#uses=1]
+ %tmp8 = trunc i64 %tmp7 to i8 ; <i8> [#uses=1]
+ %tmp10 = lshr i64 %tmp, 16 ; <i64> [#uses=1]
+ %tmp11 = trunc i64 %tmp10 to i8 ; <i8> [#uses=1]
+ %tmp13 = lshr i64 %tmp, 24 ; <i64> [#uses=1]
+ %tmp14 = trunc i64 %tmp13 to i8 ; <i8> [#uses=1]
+ %tmp1 = zext i8 %tmp5 to i32 ; <i32> [#uses=1]
+ %tmp2 = zext i8 %tmp8 to i32 ; <i32> [#uses=1]
+ %tmp3 = shl i32 %tmp2, 8 ; <i32> [#uses=1]
+ %tmp4 = zext i8 %tmp11 to i32 ; <i32> [#uses=1]
+ %tmp6 = shl i32 %tmp4, 16 ; <i32> [#uses=1]
+ %tmp9 = zext i8 %tmp14 to i32 ; <i32> [#uses=1]
+ %tmp12 = shl i32 %tmp9, 24 ; <i32> [#uses=1]
+ %tmp15 = or i32 %tmp12, %tmp1 ; <i32> [#uses=1]
+ %tmp16 = or i32 %tmp15, %tmp6 ; <i32> [#uses=1]
+ %tmp17 = or i32 %tmp16, %tmp3 ; <i32> [#uses=1]
+ ret i32 %tmp17
+}
+