[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / PhaseOrdering / two-shifts-by-sext.ll
blob4d4a30e00eafbef422784ad66d55bc1b3bfff8a1
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -O1 -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-01
3 ; RUN: opt -O2 -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-02
4 ; RUN: opt -O3 -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-03
6 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 target triple = "x86_64-unknown-linux-gnu"
9 ; int two_shifts_by_sext(int val, char len) {
10 ;   return (val << len) >> len;
11 ; }
13 ; int two_shifts_by_same_sext(int val, char len) {
14 ;   int wide_len = len;
15 ;   return (val << wide_len) >> wide_len;
16 ; }
18 ; void use_int32(int);
19 ; int two_shifts_by_sext_with_extra_use(int val, char len) {
20 ;   use_int32(len);
21 ;   return (val << len) >> len;
22 ; }
24 ; int two_shifts_by_same_sext_with_extra_use(int val, char len) {
25 ;   int wide_len = len;
26 ;   use_int32(wide_len);
27 ;   return (val << wide_len) >> wide_len;
28 ; }
30 define i32 @two_shifts_by_sext(i32 %val, i8 signext %len) {
31 ; CHECK-LABEL: @two_shifts_by_sext(
32 ; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
33 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
34 ; CHECK-NEXT:    [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
35 ; CHECK-NEXT:    ret i32 [[SHR]]
37   %val.addr = alloca i32, align 4
38   %len.addr = alloca i8, align 1
39   store i32 %val, i32* %val.addr, align 4
40   store i8 %len, i8* %len.addr, align 1
41   %val.reloaded = load i32, i32* %val.addr, align 4
42   %len.reloaded.0 = load i8, i8* %len.addr, align 1
43   %conv = sext i8 %len.reloaded.0 to i32
44   %shl = shl i32 %val.reloaded, %conv
45   %len.reloaded.1 = load i8, i8* %len.addr, align 1
46   %conv1 = sext i8 %len.reloaded.1 to i32
47   %shr = ashr i32 %shl, %conv1
48   ret i32 %shr
51 define i32 @two_shifts_by_same_sext(i32 %val, i8 signext %len) {
52 ; CHECK-LABEL: @two_shifts_by_same_sext(
53 ; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
54 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
55 ; CHECK-NEXT:    [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
56 ; CHECK-NEXT:    ret i32 [[SHR]]
58   %val.addr = alloca i32, align 4
59   %len.addr = alloca i8, align 1
60   %wide_len = alloca i32, align 4
61   store i32 %val, i32* %val.addr, align 4
62   store i8 %len, i8* %len.addr, align 1
63   %len.reloaded.0 = load i8, i8* %len.addr, align 1
64   %conv = sext i8 %len.reloaded.0 to i32
65   store i32 %conv, i32* %wide_len, align 4
66   %val.reloaded = load i32, i32* %val.addr, align 4
67   %len.reloaded.1 = load i32, i32* %wide_len, align 4
68   %shl = shl i32 %val.reloaded, %len.reloaded.1
69   %len.reloaded.2 = load i32, i32* %wide_len, align 4
70   %shr = ashr i32 %shl, %len.reloaded.2
71   ret i32 %shr
74 define i32 @two_shifts_by_sext_with_extra_use(i32 %val, i8 signext %len) {
75 ; CHECK-LABEL: @two_shifts_by_sext_with_extra_use(
76 ; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
77 ; CHECK-NEXT:    tail call void @use_int32(i32 [[CONV]])
78 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
79 ; CHECK-NEXT:    [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
80 ; CHECK-NEXT:    ret i32 [[SHR]]
82   %val.addr = alloca i32, align 4
83   %len.addr = alloca i8, align 1
84   store i32 %val, i32* %val.addr, align 4
85   store i8 %len, i8* %len.addr, align 1
86   %len.reloaded.0 = load i8, i8* %len.addr, align 1
87   %conv = sext i8 %len.reloaded.0 to i32
88   call void @use_int32(i32 %conv)
89   %val.reloaded = load i32, i32* %val.addr, align 4
90   %len.reloaded.1 = load i8, i8* %len.addr, align 1
91   %conv1 = sext i8 %len.reloaded.1 to i32
92   %shl = shl i32 %val.reloaded, %conv1
93   %len.reloaded.2 = load i8, i8* %len.addr, align 1
94   %conv2 = sext i8 %len.reloaded.2 to i32
95   %shr = ashr i32 %shl, %conv2
96   ret i32 %shr
99 declare void @use_int32(i32)
101 define i32 @two_shifts_by_same_sext_with_extra_use(i32 %val, i8 signext %len) {
102 ; CHECK-LABEL: @two_shifts_by_same_sext_with_extra_use(
103 ; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
104 ; CHECK-NEXT:    tail call void @use_int32(i32 [[CONV]])
105 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
106 ; CHECK-NEXT:    [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
107 ; CHECK-NEXT:    ret i32 [[SHR]]
109   %val.addr = alloca i32, align 4
110   %len.addr = alloca i8, align 1
111   %wide_len = alloca i32, align 4
112   store i32 %val, i32* %val.addr, align 4
113   store i8 %len, i8* %len.addr, align 1
114   %len.reloaded.0 = load i8, i8* %len.addr, align 1
115   %conv = sext i8 %len.reloaded.0 to i32
116   store i32 %conv, i32* %wide_len, align 4
117   %val.reloaded = load i32, i32* %wide_len, align 4
118   call void @use_int32(i32 %val.reloaded)
119   %len.reloaded.1 = load i32, i32* %val.addr, align 4
120   %len.reloaded.2 = load i32, i32* %wide_len, align 4
121   %shl = shl i32 %len.reloaded.1, %len.reloaded.2
122   %wide_len.reloaded = load i32, i32* %wide_len, align 4
123   %shr = ashr i32 %shl, %wide_len.reloaded
124   ret i32 %shr