@@ -5,7 +5,136 @@ declare i8 @llvm.abs.i8(i8, i1)
5
5
declare i32 @llvm.abs.i32 (i32 , i1 )
6
6
declare <4 x i32 > @llvm.abs.v4i32 (<4 x i32 >, i1 )
7
7
declare <3 x i82 > @llvm.abs.v3i82 (<3 x i82 >, i1 )
8
+ declare <2 x i8 > @llvm.abs.v2i8 (<2 x i8 >, i1 )
8
9
declare void @llvm.assume (i1 )
10
+ declare void @use (i32 )
11
+
12
+ define i8 @test_abs_abs_a_mul_b_i8 (i8 %a , i8 %b ) {
13
+ ; CHECK-LABEL: @test_abs_abs_a_mul_b_i8(
14
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul i8 [[B:%.*]], [[A:%.*]]
15
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i8 @llvm.abs.i8(i8 [[TMP1]], i1 true)
16
+ ; CHECK-NEXT: ret i8 [[ABS2]]
17
+ ;
18
+ %abs1 = call i8 @llvm.abs.i8 (i8 %a , i1 true )
19
+ %mul = mul i8 %abs1 , %b
20
+ %abs2 = call i8 @llvm.abs.i8 (i8 %mul , i1 true )
21
+ ret i8 %abs2
22
+ }
23
+
24
+ define i8 @test_abs_a_mul_abs_b_i8 (i8 %a , i8 %b ) {
25
+ ; CHECK-LABEL: @test_abs_a_mul_abs_b_i8(
26
+ ; CHECK-NEXT: [[A1:%.*]] = urem i8 123, [[A:%.*]]
27
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul i8 [[A1]], [[B:%.*]]
28
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i8 @llvm.abs.i8(i8 [[TMP1]], i1 true)
29
+ ; CHECK-NEXT: ret i8 [[ABS2]]
30
+ ;
31
+ %a1 = urem i8 123 , %a ; thwart complexity-based canonicalization
32
+ %abs1 = call i8 @llvm.abs.i8 (i8 %b , i1 true )
33
+ %mul = mul i8 %a1 , %abs1
34
+ %abs2 = call i8 @llvm.abs.i8 (i8 %mul , i1 true )
35
+ ret i8 %abs2
36
+ }
37
+
38
+ define i32 @test_abs_abs_a_mul_b_i32 (i32 %a , i32 %b ) {
39
+ ; CHECK-LABEL: @test_abs_abs_a_mul_b_i32(
40
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[B:%.*]], [[A:%.*]]
41
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true)
42
+ ; CHECK-NEXT: ret i32 [[ABS2]]
43
+ ;
44
+ %abs1 = call i32 @llvm.abs.i32 (i32 %a , i1 true )
45
+ %mul = mul i32 %abs1 , %b
46
+ %abs2 = call i32 @llvm.abs.i32 (i32 %mul , i1 true )
47
+ ret i32 %abs2
48
+ }
49
+
50
+ define i32 @test_abs_abs_a_mul_b_i32_abs_false_true (i32 %a , i32 %b ) {
51
+ ; CHECK-LABEL: @test_abs_abs_a_mul_b_i32_abs_false_true(
52
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[B:%.*]], [[A:%.*]]
53
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true)
54
+ ; CHECK-NEXT: ret i32 [[ABS2]]
55
+ ;
56
+ %abs1 = call i32 @llvm.abs.i32 (i32 %a , i1 false )
57
+ %mul = mul i32 %abs1 , %b
58
+ %abs2 = call i32 @llvm.abs.i32 (i32 %mul , i1 true )
59
+ ret i32 %abs2
60
+ }
61
+
62
+ define i32 @test_abs_abs_a_mul_b_i32_abs_true_false (i32 %a , i32 %b ) {
63
+ ; CHECK-LABEL: @test_abs_abs_a_mul_b_i32_abs_true_false(
64
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[B:%.*]], [[A:%.*]]
65
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 false)
66
+ ; CHECK-NEXT: ret i32 [[ABS2]]
67
+ ;
68
+ %abs1 = call i32 @llvm.abs.i32 (i32 %a , i1 true )
69
+ %mul = mul i32 %abs1 , %b
70
+ %abs2 = call i32 @llvm.abs.i32 (i32 %mul , i1 false )
71
+ ret i32 %abs2
72
+ }
73
+
74
+ define i32 @test_abs_abs_a_mul_b_i32_abs_false_false (i32 %a , i32 %b ) {
75
+ ; CHECK-LABEL: @test_abs_abs_a_mul_b_i32_abs_false_false(
76
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[B:%.*]], [[A:%.*]]
77
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 false)
78
+ ; CHECK-NEXT: ret i32 [[ABS2]]
79
+ ;
80
+ %abs1 = call i32 @llvm.abs.i32 (i32 %a , i1 false )
81
+ %mul = mul i32 %abs1 , %b
82
+ %abs2 = call i32 @llvm.abs.i32 (i32 %mul , i1 false )
83
+ ret i32 %abs2
84
+ }
85
+
86
+ ; this should work
87
+ define i8 @test_nsw_with_true (i8 %a , i8 %b ) {
88
+ ; CHECK-LABEL: @test_nsw_with_true(
89
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i8 [[B:%.*]], [[A:%.*]]
90
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i8 @llvm.abs.i8(i8 [[TMP1]], i1 true)
91
+ ; CHECK-NEXT: ret i8 [[ABS2]]
92
+ ;
93
+ %abs1 = call i8 @llvm.abs.i8 (i8 %a , i1 false )
94
+ %mul = mul nsw i8 %abs1 , %b
95
+ %abs2 = call i8 @llvm.abs.i8 (i8 %mul , i1 true )
96
+ ret i8 %abs2
97
+ }
98
+
99
+ ; this should't propagate the nsw
100
+ define i8 @test_nsw_with_false (i8 %a , i8 %b ) {
101
+ ; CHECK-LABEL: @test_nsw_with_false(
102
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul i8 [[B:%.*]], [[A:%.*]]
103
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i8 @llvm.abs.i8(i8 [[TMP1]], i1 false)
104
+ ; CHECK-NEXT: ret i8 [[ABS2]]
105
+ ;
106
+ %abs1 = call i8 @llvm.abs.i8 (i8 %a , i1 false )
107
+ %mul = mul nsw i8 %abs1 , %b
108
+ %abs2 = call i8 @llvm.abs.i8 (i8 %mul , i1 false )
109
+ ret i8 %abs2
110
+ }
111
+
112
+ define i32 @test_abs_abs_a_mul_b_more_one_use (i32 %a , i32 %b ) {
113
+ ; CHECK-LABEL: @test_abs_abs_a_mul_b_more_one_use(
114
+ ; CHECK-NEXT: [[ABS1:%.*]] = call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 true)
115
+ ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ABS1]], [[B:%.*]]
116
+ ; CHECK-NEXT: [[ABS2:%.*]] = call i32 @llvm.abs.i32(i32 [[MUL]], i1 false)
117
+ ; CHECK-NEXT: call void @use(i32 [[MUL]])
118
+ ; CHECK-NEXT: ret i32 [[ABS2]]
119
+ ;
120
+ %abs1 = call i32 @llvm.abs.i32 (i32 %a , i1 true )
121
+ %mul = mul i32 %abs1 , %b
122
+ %abs2 = call i32 @llvm.abs.i32 (i32 %mul , i1 false )
123
+ call void @use (i32 %mul )
124
+ ret i32 %abs2
125
+ }
126
+
127
+ define <2 x i8 > @test_abs_abs_a_mul_b_vector_i8 (<2 x i8 > %a , <2 x i8 > %b ) {
128
+ ; CHECK-LABEL: @test_abs_abs_a_mul_b_vector_i8(
129
+ ; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i8> [[B:%.*]], [[A:%.*]]
130
+ ; CHECK-NEXT: [[ABS2:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[TMP1]], i1 true)
131
+ ; CHECK-NEXT: ret <2 x i8> [[ABS2]]
132
+ ;
133
+ %abs = call <2 x i8 > @llvm.abs.v2i8 (<2 x i8 > %a , i1 true )
134
+ %mul = mul <2 x i8 > %abs , %b
135
+ %abs2 = call <2 x i8 > @llvm.abs.v2i8 (<2 x i8 > %mul , i1 true )
136
+ ret <2 x i8 > %abs2
137
+ }
9
138
10
139
; abs preserves trailing zeros so the second and is unneeded
11
140
define i32 @abs_trailing_zeros (i32 %x ) {
0 commit comments