diff options
-rw-r--r-- | llvm/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/llvm/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll b/llvm/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll new file mode 100644 index 00000000000..1347e20585a --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll @@ -0,0 +1,123 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +; %r = shl nuw i8 C, %x +; As per langref: If the nuw keyword is present, then the shift produces +; a poison value if it shifts out any non-zero bits. +; Thus, if the sign bit is set on C, then %x can only be 0, which means that +; %r can only be C. + +define i8 @shl_nuw (i8 %x) { +; CHECK-LABEL: @shl_nuw( +; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 -1, [[X:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %ret = shl nuw i8 -1, %x + ; nuw here means that %x can only be 0 + ret i8 %ret +} + +define i8 @shl_nuw_nsw (i8 %x) { +; CHECK-LABEL: @shl_nuw_nsw( +; CHECK-NEXT: [[RET:%.*]] = shl nuw nsw i8 -1, [[X:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %ret = shl nuw nsw i8 -1, %x + ; nuw here means that %x can only be 0 + ret i8 %ret +} + +define i8 @shl_128 (i8 %x) { +; CHECK-LABEL: @shl_128( +; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 -128, [[X:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %ret = shl nuw i8 128, %x + ; 128 == 1<<7 == just the sign bit is set + ret i8 %ret +} + +; ============================================================================ ; +; Vectors +; ============================================================================ ; + +define <2 x i8> @shl_vec(<2 x i8> %x) { +; CHECK-LABEL: @shl_vec( +; CHECK-NEXT: [[RET:%.*]] = shl nuw <2 x i8> <i8 -1, i8 -1>, [[X:%.*]] +; CHECK-NEXT: ret <2 x i8> [[RET]] +; + %ret = shl nuw <2 x i8> <i8 -1, i8 -1>, %x + ret <2 x i8> %ret +} + +define <3 x i8> @shl_vec_undef(<3 x i8> %x) { +; CHECK-LABEL: @shl_vec_undef( +; CHECK-NEXT: [[RET:%.*]] = shl nuw <3 x i8> <i8 -1, i8 undef, i8 -1>, [[X:%.*]] +; CHECK-NEXT: ret <3 x i8> [[RET]] +; + %ret = shl nuw <3 x i8> <i8 -1, i8 undef, i8 -1>, %x + ret <3 x i8> %ret +} + +define <2 x i8> @shl_vec_nonsplat(<2 x i8> %x) { +; CHECK-LABEL: @shl_vec_nonsplat( +; CHECK-NEXT: [[RET:%.*]] = shl nuw <2 x i8> <i8 -1, i8 -2>, [[X:%.*]] +; CHECK-NEXT: ret <2 x i8> [[RET]] +; + %ret = shl nuw <2 x i8> <i8 -1, i8 -2>, %x + ret <2 x i8> %ret +} + +; ============================================================================ ; +; Negative tests. Should not be folded. +; ============================================================================ ; + +define i8 @shl_127 (i8 %x) { +; CHECK-LABEL: @shl_127( +; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 127, [[X:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %ret = shl nuw i8 127, %x + ; 127 == (1<<7)-1 == all bits except the sign bit are set. + ret i8 %ret +} + +define i8 @bad_nsw (i8 %x) { +; CHECK-LABEL: @bad_nsw( +; CHECK-NEXT: [[RET:%.*]] = shl nsw i8 -1, [[X:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %ret = shl nsw i8 -1, %x + ret i8 %ret +} + +; First `shl` operand is not `-1` constant + +define i8 @bad_shl0(i8 %shlop1, i8 %x) { +; CHECK-LABEL: @bad_shl0( +; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 [[SHLOP1:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %ret = shl nuw i8 %shlop1, %x + ret i8 %ret +} + +; Bad shl nuw constant + +define i8 @bad_shl1(i8 %x) { +; CHECK-LABEL: @bad_shl1( +; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 1, [[X:%.*]] +; CHECK-NEXT: ret i8 [[RET]] +; + %ret = shl nuw i8 1, %x ; not -1 + ret i8 %ret +} + +define <2 x i8> @bad_shl_vec_nonsplat(<2 x i8> %x) { +; CHECK-LABEL: @bad_shl_vec_nonsplat( +; CHECK-NEXT: [[RET:%.*]] = shl nuw <2 x i8> <i8 -1, i8 1>, [[X:%.*]] +; CHECK-NEXT: ret <2 x i8> [[RET]] +; + %ret = shl nuw <2 x i8> <i8 -1, i8 1>, %x + ret <2 x i8> %ret +} |