aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPawel Bylica <chfast@gmail.com>2015-04-29 14:57:35 +0000
committerPawel Bylica <chfast@gmail.com>2015-04-29 14:57:35 +0000
commitf1975e4c5ffac07cc067be85c722e0926d45f3d5 (patch)
treef765f1bdc0064b86270d018ffb3e8c6244491bf1
parentec52f310649213a7c1864122dca44bfbd686c90d (diff)
Merge r232176: 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/branches/release_36@236109 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/IR/ConstantFold.cpp33
-rw-r--r--test/Transforms/ConstProp/shift.ll69
2 files changed, 81 insertions, 21 deletions
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index 9176bf2aeee..39d9a1d0a28 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -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
}
}
diff --git a/test/Transforms/ConstProp/shift.ll b/test/Transforms/ConstProp/shift.ll
new file mode 100644
index 00000000000..de23fe98ad8
--- /dev/null
+++ b/test/Transforms/ConstProp/shift.ll
@@ -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
+}