summaryrefslogtreecommitdiff
path: root/test/CodeGen/SystemZ/insert-06.ll
blob: 8366b2c79791a9f99e58bd639fb3c6315268b3e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
; Test insertions of i32s into the low half of an i64.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s

; Insertion of an i32 can be done using LR.
define i64 @f1(i64 %a, i32 %b) {
; CHECK-LABEL: f1:
; CHECK-NOT: {{%r[23]}}
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %low = zext i32 %b to i64
  %high = and i64 %a, -4294967296
  %res = or i64 %high, %low
  ret i64 %res
}

; ... and again with the operands reversed.
define i64 @f2(i64 %a, i32 %b) {
; CHECK-LABEL: f2:
; CHECK-NOT: {{%r[23]}}
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %low = zext i32 %b to i64
  %high = and i64 %a, -4294967296
  %res = or i64 %low, %high
  ret i64 %res
}

; Like f1, but with "in register" zero extension.
define i64 @f3(i64 %a, i64 %b) {
; CHECK-LABEL: f3:
; CHECK-NOT: {{%r[23]}}
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %low = and i64 %b, 4294967295
  %high = and i64 %a, -4294967296
  %res = or i64 %high, %low
  ret i64 %res
}

; ... and again with the operands reversed.
define i64 @f4(i64 %a, i64 %b) {
; CHECK-LABEL: f4:
; CHECK-NOT: {{%r[23]}}
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %low = and i64 %b, 4294967295
  %high = and i64 %a, -4294967296
  %res = or i64 %low, %high
  ret i64 %res
}

; Unary operations can be done directly into the low half.
define i64 @f5(i64 %a, i32 %b) {
; CHECK-LABEL: f5:
; CHECK-NOT: {{%r[23]}}
; CHECK: lcr %r2, %r3
; CHECK: br %r14
  %neg = sub i32 0, %b
  %low = zext i32 %neg to i64
  %high = and i64 %a, -4294967296
  %res = or i64 %high, %low
  ret i64 %res
}

; ...likewise three-operand binary operations like RLL.
define i64 @f6(i64 %a, i32 %b) {
; CHECK-LABEL: f6:
; CHECK-NOT: {{%r[23]}}
; CHECK: rll %r2, %r3, 1
; CHECK: br %r14
  %parta = shl i32 %b, 1
  %partb = lshr i32 %b, 31
  %rot = or i32 %parta, %partb
  %low = zext i32 %rot to i64
  %high = and i64 %a, -4294967296
  %res = or i64 %low, %high
  ret i64 %res
}

; Loads can be done directly into the low half.  The range of L is checked
; in the move tests.
define i64 @f7(i64 %a, i32 *%src) {
; CHECK-LABEL: f7:
; CHECK-NOT: {{%r[23]}}
; CHECK: l %r2, 0(%r3)
; CHECK: br %r14
  %b = load i32 *%src
  %low = zext i32 %b to i64
  %high = and i64 %a, -4294967296
  %res = or i64 %high, %low
  ret i64 %res
}

; ...likewise extending loads.
define i64 @f8(i64 %a, i8 *%src) {
; CHECK-LABEL: f8:
; CHECK-NOT: {{%r[23]}}
; CHECK: lb %r2, 0(%r3)
; CHECK: br %r14
  %byte = load i8 *%src
  %b = sext i8 %byte to i32
  %low = zext i32 %b to i64
  %high = and i64 %a, -4294967296
  %res = or i64 %high, %low
  ret i64 %res
}

; Check a case like f1 in which there is no AND.  We simply know from context
; that the upper half of one OR operand and the lower half of the other are
; both clear.
define i64 @f9(i64 %a, i32 %b) {
; CHECK-LABEL: f9:
; CHECK: sllg %r2, %r2, 32
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %shift = shl i64 %a, 32
  %low = zext i32 %b to i64
  %or = or i64 %shift, %low
  ret i64 %or
}

; ...and again with the operands reversed.
define i64 @f10(i64 %a, i32 %b) {
; CHECK-LABEL: f10:
; CHECK: sllg %r2, %r2, 32
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %shift = shl i64 %a, 32
  %low = zext i32 %b to i64
  %or = or i64 %low, %shift
  ret i64 %or
}

; Like f9, but with "in register" zero extension.
define i64 @f11(i64 %a, i64 %b) {
; CHECK-LABEL: f11:
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %shift = shl i64 %a, 32
  %low = and i64 %b, 4294967295
  %or = or i64 %shift, %low
  ret i64 %or
}

; ...and again with the operands reversed.
define i64 @f12(i64 %a, i64 %b) {
; CHECK-LABEL: f12:
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %shift = shl i64 %a, 32
  %low = and i64 %b, 4294967295
  %or = or i64 %low, %shift
  ret i64 %or
}

; Like f9, but for larger shifts than 32.
define i64 @f13(i64 %a, i32 %b) {
; CHECK-LABEL: f13:
; CHECK: sllg %r2, %r2, 60
; CHECK: lr %r2, %r3
; CHECK: br %r14
  %shift = shl i64 %a, 60
  %low = zext i32 %b to i64
  %or = or i64 %shift, %low
  ret i64 %or
}