ConstantFold: Fix big shift constant folding

Constant folding for shift IR instructions ignores all bits above 32 of
second argument (shift amount).
Because of that, some undef results are not recognized and APInt can
raise an assert failure if second argument has more than 64 bits.

Patch by Paweł Bylica!

Differential Revision: http://reviews.llvm.org/D7701

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232176 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2015-03-13 16:39:46 +00:00
parent 547ba56bd0
commit 790aec0651
2 changed files with 81 additions and 21 deletions

View File

@ -1120,27 +1120,18 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
return ConstantInt::get(CI1->getContext(), C1V | C2V);
case Instruction::Xor:
return ConstantInt::get(CI1->getContext(), C1V ^ C2V);
case Instruction::Shl: {
uint32_t shiftAmt = C2V.getZExtValue();
if (shiftAmt < C1V.getBitWidth())
return ConstantInt::get(CI1->getContext(), C1V.shl(shiftAmt));
else
return UndefValue::get(C1->getType()); // too big shift is undef
}
case Instruction::LShr: {
uint32_t shiftAmt = C2V.getZExtValue();
if (shiftAmt < C1V.getBitWidth())
return ConstantInt::get(CI1->getContext(), C1V.lshr(shiftAmt));
else
return UndefValue::get(C1->getType()); // too big shift is undef
}
case Instruction::AShr: {
uint32_t shiftAmt = C2V.getZExtValue();
if (shiftAmt < C1V.getBitWidth())
return ConstantInt::get(CI1->getContext(), C1V.ashr(shiftAmt));
else
return UndefValue::get(C1->getType()); // too big shift is undef
}
case Instruction::Shl:
if (C2V.ult(C1V.getBitWidth()))
return ConstantInt::get(CI1->getContext(), C1V.shl(C2V));
return UndefValue::get(C1->getType()); // too big shift is undef
case Instruction::LShr:
if (C2V.ult(C1V.getBitWidth()))
return ConstantInt::get(CI1->getContext(), C1V.lshr(C2V));
return UndefValue::get(C1->getType()); // too big shift is undef
case Instruction::AShr:
if (C2V.ult(C1V.getBitWidth()))
return ConstantInt::get(CI1->getContext(), C1V.ashr(C2V));
return UndefValue::get(C1->getType()); // too big shift is undef
}
}

View File

@ -0,0 +1,69 @@
; RUN: opt < %s -constprop -S | FileCheck %s
; CHECK-LABEL: shift_undef_64
define void @shift_undef_64(i64* %p) {
%r1 = lshr i64 -1, 4294967296 ; 2^32
; CHECK: store i64 undef
store i64 %r1, i64* %p
%r2 = ashr i64 -1, 4294967297 ; 2^32 + 1
; CHECK: store i64 undef
store i64 %r2, i64* %p
%r3 = shl i64 -1, 4294967298 ; 2^32 + 2
; CHECK: store i64 undef
store i64 %r3, i64* %p
ret void
}
; CHECK-LABEL: shift_undef_65
define void @shift_undef_65(i65* %p) {
%r1 = lshr i65 2, 18446744073709551617
; CHECK: store i65 undef
store i65 %r1, i65* %p
%r2 = ashr i65 4, 18446744073709551617
; CHECK: store i65 undef
store i65 %r2, i65* %p
%r3 = shl i65 1, 18446744073709551617
; CHECK: store i65 undef
store i65 %r3, i65* %p
ret void
}
; CHECK-LABEL: shift_undef_256
define void @shift_undef_256(i256* %p) {
%r1 = lshr i256 2, 18446744073709551617
; CHECK: store i256 undef
store i256 %r1, i256* %p
%r2 = ashr i256 4, 18446744073709551618
; CHECK: store i256 undef
store i256 %r2, i256* %p
%r3 = shl i256 1, 18446744073709551619
; CHECK: store i256 undef
store i256 %r3, i256* %p
ret void
}
; CHECK-LABEL: shift_undef_511
define void @shift_undef_511(i511* %p) {
%r1 = lshr i511 -1, 1208925819614629174706276 ; 2^80 + 100
; CHECK: store i511 undef
store i511 %r1, i511* %p
%r2 = ashr i511 -2, 1208925819614629174706200
; CHECK: store i511 undef
store i511 %r2, i511* %p
%r3 = shl i511 -3, 1208925819614629174706180
; CHECK: store i511 undef
store i511 %r3, i511* %p
ret void
}