1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=i686-- -mattr=sse2 | FileCheck %s --check-prefixes=ANY,X32-SSE2 3; RUN: llc < %s -mtriple=x86_64-- -mattr=avx2 | FileCheck %s --check-prefixes=ANY,X64-AVX2 4 5declare i8 @llvm.fshl.i8(i8, i8, i8) 6declare i16 @llvm.fshl.i16(i16, i16, i16) 7declare i32 @llvm.fshl.i32(i32, i32, i32) 8declare i64 @llvm.fshl.i64(i64, i64, i64) 9declare <4 x i32> @llvm.fshl.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) 10declare i128 @llvm.fshl.i128(i128, i128, i128) 11 12declare i8 @llvm.fshr.i8(i8, i8, i8) 13declare i16 @llvm.fshr.i16(i16, i16, i16) 14declare i32 @llvm.fshr.i32(i32, i32, i32) 15declare i64 @llvm.fshr.i64(i64, i64, i64) 16declare <4 x i32> @llvm.fshr.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) 17 18; General case - all operands can be variables 19 20define i32 @fshl_i32(i32 %x, i32 %y, i32 %z) nounwind { 21; X32-SSE2-LABEL: fshl_i32: 22; X32-SSE2: # %bb.0: 23; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 24; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 25; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 26; X32-SSE2-NEXT: shldl %cl, %edx, %eax 27; X32-SSE2-NEXT: retl 28; 29; X64-AVX2-LABEL: fshl_i32: 30; X64-AVX2: # %bb.0: 31; X64-AVX2-NEXT: movl %edx, %ecx 32; X64-AVX2-NEXT: movl %edi, %eax 33; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 34; X64-AVX2-NEXT: shldl %cl, %esi, %eax 35; X64-AVX2-NEXT: retq 36 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %z) 37 ret i32 %f 38} 39 40define i64 @fshl_i64(i64 %x, i64 %y, i64 %z) nounwind { 41; X32-SSE2-LABEL: fshl_i64: 42; X32-SSE2: # %bb.0: 43; X32-SSE2-NEXT: pushl %ebp 44; X32-SSE2-NEXT: pushl %ebx 45; X32-SSE2-NEXT: pushl %edi 46; X32-SSE2-NEXT: pushl %esi 47; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edi 48; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 49; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi 50; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebx 51; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %ch 52; X32-SSE2-NEXT: movb %ch, %cl 53; X32-SSE2-NEXT: notb %cl 54; X32-SSE2-NEXT: shrdl $1, %ebx, %esi 55; X32-SSE2-NEXT: shrl %ebx 56; X32-SSE2-NEXT: shrdl %cl, %ebx, %esi 57; X32-SSE2-NEXT: shrl %cl, %ebx 58; X32-SSE2-NEXT: xorl %ebp, %ebp 59; X32-SSE2-NEXT: testb $32, %cl 60; X32-SSE2-NEXT: cmovnel %ebx, %esi 61; X32-SSE2-NEXT: cmovnel %ebp, %ebx 62; X32-SSE2-NEXT: movl %edi, %eax 63; X32-SSE2-NEXT: movb %ch, %cl 64; X32-SSE2-NEXT: shll %cl, %eax 65; X32-SSE2-NEXT: shldl %cl, %edi, %edx 66; X32-SSE2-NEXT: testb $32, %ch 67; X32-SSE2-NEXT: cmovnel %eax, %edx 68; X32-SSE2-NEXT: cmovnel %ebp, %eax 69; X32-SSE2-NEXT: orl %esi, %eax 70; X32-SSE2-NEXT: orl %ebx, %edx 71; X32-SSE2-NEXT: popl %esi 72; X32-SSE2-NEXT: popl %edi 73; X32-SSE2-NEXT: popl %ebx 74; X32-SSE2-NEXT: popl %ebp 75; X32-SSE2-NEXT: retl 76; 77; X64-AVX2-LABEL: fshl_i64: 78; X64-AVX2: # %bb.0: 79; X64-AVX2-NEXT: movq %rdx, %rcx 80; X64-AVX2-NEXT: movq %rdi, %rax 81; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $rcx 82; X64-AVX2-NEXT: shldq %cl, %rsi, %rax 83; X64-AVX2-NEXT: retq 84 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %y, i64 %z) 85 ret i64 %f 86} 87 88define i128 @fshl_i128(i128 %x, i128 %y, i128 %z) nounwind { 89; X32-SSE2-LABEL: fshl_i128: 90; X32-SSE2: # %bb.0: 91; X32-SSE2-NEXT: pushl %ebp 92; X32-SSE2-NEXT: pushl %ebx 93; X32-SSE2-NEXT: pushl %edi 94; X32-SSE2-NEXT: pushl %esi 95; X32-SSE2-NEXT: subl $64, %esp 96; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebx 97; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 98; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi 99; X32-SSE2-NEXT: movl %esi, %edi 100; X32-SSE2-NEXT: shldl $31, %ecx, %edi 101; X32-SSE2-NEXT: notl %ebx 102; X32-SSE2-NEXT: andl $127, %ebx 103; X32-SSE2-NEXT: movb $64, %cl 104; X32-SSE2-NEXT: subb %bl, %cl 105; X32-SSE2-NEXT: shrl %esi 106; X32-SSE2-NEXT: movl %esi, (%esp) # 4-byte Spill 107; X32-SSE2-NEXT: shldl %cl, %edi, %esi 108; X32-SSE2-NEXT: movl %edi, %ebp 109; X32-SSE2-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 110; X32-SSE2-NEXT: shll %cl, %ebp 111; X32-SSE2-NEXT: xorl %eax, %eax 112; X32-SSE2-NEXT: testb $32, %cl 113; X32-SSE2-NEXT: cmovnel %ebp, %esi 114; X32-SSE2-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 115; X32-SSE2-NEXT: cmovnel %eax, %ebp 116; X32-SSE2-NEXT: movl %ebp, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 117; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 118; X32-SSE2-NEXT: andl $127, %eax 119; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebp 120; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 121; X32-SSE2-NEXT: movl %eax, %ecx 122; X32-SSE2-NEXT: shldl %cl, %ebp, %edx 123; X32-SSE2-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 124; X32-SSE2-NEXT: movl %ebx, %ecx 125; X32-SSE2-NEXT: addb $-64, %cl 126; X32-SSE2-NEXT: movl (%esp), %esi # 4-byte Reload 127; X32-SSE2-NEXT: shrdl %cl, %esi, %edi 128; X32-SSE2-NEXT: shrl %cl, %esi 129; X32-SSE2-NEXT: testb $32, %cl 130; X32-SSE2-NEXT: cmovnel %esi, %edi 131; X32-SSE2-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 132; X32-SSE2-NEXT: movl $0, %ecx 133; X32-SSE2-NEXT: cmovnel %ecx, %esi 134; X32-SSE2-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 135; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edi 136; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi 137; X32-SSE2-NEXT: movl %eax, %ecx 138; X32-SSE2-NEXT: shldl %cl, %edi, %esi 139; X32-SSE2-NEXT: movl %edi, %edx 140; X32-SSE2-NEXT: shll %cl, %edx 141; X32-SSE2-NEXT: shll %cl, %ebp 142; X32-SSE2-NEXT: testb $32, %al 143; X32-SSE2-NEXT: movl %eax, %ecx 144; X32-SSE2-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 145; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload 146; X32-SSE2-NEXT: cmovnel %ebp, %eax 147; X32-SSE2-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 148; X32-SSE2-NEXT: cmovnel %edx, %esi 149; X32-SSE2-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 150; X32-SSE2-NEXT: movl $0, %eax 151; X32-SSE2-NEXT: cmovnel %eax, %ebp 152; X32-SSE2-NEXT: movl %ebp, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 153; X32-SSE2-NEXT: cmovnel %eax, %edx 154; X32-SSE2-NEXT: xorl %eax, %eax 155; X32-SSE2-NEXT: cmpl $64, %ecx 156; X32-SSE2-NEXT: cmovael %eax, %edx 157; X32-SSE2-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 158; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 159; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebp 160; X32-SSE2-NEXT: shldl $31, %eax, %ebp 161; X32-SSE2-NEXT: movl %ebp, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 162; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi 163; X32-SSE2-NEXT: shrdl $1, %eax, %esi 164; X32-SSE2-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 165; X32-SSE2-NEXT: movl %ebx, %ecx 166; X32-SSE2-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 167; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload 168; X32-SSE2-NEXT: movl (%esp), %edx # 4-byte Reload 169; X32-SSE2-NEXT: shrdl %cl, %edx, %eax 170; X32-SSE2-NEXT: shrl %cl, %edx 171; X32-SSE2-NEXT: movl %esi, %ebx 172; X32-SSE2-NEXT: shrdl %cl, %ebp, %ebx 173; X32-SSE2-NEXT: movl %ebp, %esi 174; X32-SSE2-NEXT: shrl %cl, %esi 175; X32-SSE2-NEXT: testb $32, %cl 176; X32-SSE2-NEXT: cmovnel %esi, %ebx 177; X32-SSE2-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 178; X32-SSE2-NEXT: movl %edx, %ecx 179; X32-SSE2-NEXT: cmovnel %edx, %eax 180; X32-SSE2-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 181; X32-SSE2-NEXT: movl $0, %eax 182; X32-SSE2-NEXT: cmovnel %eax, %esi 183; X32-SSE2-NEXT: cmovnel %eax, %ecx 184; X32-SSE2-NEXT: movl %ecx, (%esp) # 4-byte Spill 185; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload 186; X32-SSE2-NEXT: cmpl $64, %ebx 187; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload 188; X32-SSE2-NEXT: cmovael %eax, %ecx 189; X32-SSE2-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 190; X32-SSE2-NEXT: xorl %ebp, %ebp 191; X32-SSE2-NEXT: movb $64, %ch 192; X32-SSE2-NEXT: subb %bl, %ch 193; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 194; X32-SSE2-NEXT: movb %ch, %cl 195; X32-SSE2-NEXT: shrl %cl, %edx 196; X32-SSE2-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 197; X32-SSE2-NEXT: testb $32, %ch 198; X32-SSE2-NEXT: cmovnel %ebp, %edx 199; X32-SSE2-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload 200; X32-SSE2-NEXT: movb %bl, %cl 201; X32-SSE2-NEXT: addb $-64, %cl 202; X32-SSE2-NEXT: movl %edi, %ebp 203; X32-SSE2-NEXT: shll %cl, %ebp 204; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 205; X32-SSE2-NEXT: shldl %cl, %edi, %eax 206; X32-SSE2-NEXT: testb $32, %cl 207; X32-SSE2-NEXT: cmovnel %ebp, %eax 208; X32-SSE2-NEXT: cmpl $64, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload 209; X32-SSE2-NEXT: movl (%esp), %ebx # 4-byte Reload 210; X32-SSE2-NEXT: movl $0, %edi 211; X32-SSE2-NEXT: cmovael %edi, %ebx 212; X32-SSE2-NEXT: movl %ebx, (%esp) # 4-byte Spill 213; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload 214; X32-SSE2-NEXT: cmpl $64, %ebx 215; X32-SSE2-NEXT: cmovbl %edx, %eax 216; X32-SSE2-NEXT: testb $32, %cl 217; X32-SSE2-NEXT: movl $0, %edi 218; X32-SSE2-NEXT: cmovnel %edi, %ebp 219; X32-SSE2-NEXT: cmpl $64, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload 220; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload 221; X32-SSE2-NEXT: cmovael %edi, %edx 222; X32-SSE2-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill 223; X32-SSE2-NEXT: movb %ch, %cl 224; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 225; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edi 226; X32-SSE2-NEXT: shrdl %cl, %edx, %edi 227; X32-SSE2-NEXT: testb $32, %ch 228; X32-SSE2-NEXT: cmovnel {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload 229; X32-SSE2-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload 230; X32-SSE2-NEXT: cmpl $64, %ebx 231; X32-SSE2-NEXT: cmovael %ebp, %edi 232; X32-SSE2-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload 233; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload 234; X32-SSE2-NEXT: cmpl $64, %edx 235; X32-SSE2-NEXT: cmovael {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload 236; X32-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload 237; X32-SSE2-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload 238; X32-SSE2-NEXT: cmpl $64, %edx 239; X32-SSE2-NEXT: cmovael {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload 240; X32-SSE2-NEXT: testl %edx, %edx 241; X32-SSE2-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload 242; X32-SSE2-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload 243; X32-SSE2-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload 244; X32-SSE2-NEXT: movl %ecx, %edx 245; X32-SSE2-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload 246; X32-SSE2-NEXT: testl %ebx, %ebx 247; X32-SSE2-NEXT: cmovel {{[0-9]+}}(%esp), %eax 248; X32-SSE2-NEXT: cmovel {{[0-9]+}}(%esp), %edi 249; X32-SSE2-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload 250; X32-SSE2-NEXT: orl (%esp), %eax # 4-byte Folded Reload 251; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 252; X32-SSE2-NEXT: movl %eax, 12(%ecx) 253; X32-SSE2-NEXT: movl %edi, 8(%ecx) 254; X32-SSE2-NEXT: movl %esi, 4(%ecx) 255; X32-SSE2-NEXT: movl %edx, (%ecx) 256; X32-SSE2-NEXT: movl %ecx, %eax 257; X32-SSE2-NEXT: addl $64, %esp 258; X32-SSE2-NEXT: popl %esi 259; X32-SSE2-NEXT: popl %edi 260; X32-SSE2-NEXT: popl %ebx 261; X32-SSE2-NEXT: popl %ebp 262; X32-SSE2-NEXT: retl $4 263; 264; X64-AVX2-LABEL: fshl_i128: 265; X64-AVX2: # %bb.0: 266; X64-AVX2-NEXT: movq %r8, %r9 267; X64-AVX2-NEXT: movq %rcx, %r10 268; X64-AVX2-NEXT: movq %rdx, %r8 269; X64-AVX2-NEXT: movq %rsi, %rdx 270; X64-AVX2-NEXT: movl %r9d, %ecx 271; X64-AVX2-NEXT: shldq %cl, %rdi, %rdx 272; X64-AVX2-NEXT: shrdq $1, %r10, %r8 273; X64-AVX2-NEXT: shrq %r10 274; X64-AVX2-NEXT: notb %cl 275; X64-AVX2-NEXT: shrdq %cl, %r10, %r8 276; X64-AVX2-NEXT: shrq %cl, %r10 277; X64-AVX2-NEXT: xorl %eax, %eax 278; X64-AVX2-NEXT: testb $64, %cl 279; X64-AVX2-NEXT: cmovneq %r10, %r8 280; X64-AVX2-NEXT: cmovneq %rax, %r10 281; X64-AVX2-NEXT: movl %r9d, %ecx 282; X64-AVX2-NEXT: shlq %cl, %rdi 283; X64-AVX2-NEXT: testb $64, %r9b 284; X64-AVX2-NEXT: cmovneq %rdi, %rdx 285; X64-AVX2-NEXT: cmoveq %rdi, %rax 286; X64-AVX2-NEXT: orq %r8, %rax 287; X64-AVX2-NEXT: orq %r10, %rdx 288; X64-AVX2-NEXT: retq 289 %f = call i128 @llvm.fshl.i128(i128 %x, i128 %y, i128 %z) 290 ret i128 %f 291} 292 293; Verify that weird types are minimally supported. 294declare i37 @llvm.fshl.i37(i37, i37, i37) 295define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) nounwind { 296; X32-SSE2-LABEL: fshl_i37: 297; X32-SSE2: # %bb.0: 298; X32-SSE2-NEXT: pushl %ebp 299; X32-SSE2-NEXT: pushl %ebx 300; X32-SSE2-NEXT: pushl %edi 301; X32-SSE2-NEXT: pushl %esi 302; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi 303; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebx 304; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edi 305; X32-SSE2-NEXT: shldl $27, %ebx, %edi 306; X32-SSE2-NEXT: shll $27, %ebx 307; X32-SSE2-NEXT: shrdl $1, %edi, %ebx 308; X32-SSE2-NEXT: shrl %edi 309; X32-SSE2-NEXT: pushl $0 310; X32-SSE2-NEXT: pushl $37 311; X32-SSE2-NEXT: pushl {{[0-9]+}}(%esp) 312; X32-SSE2-NEXT: pushl {{[0-9]+}}(%esp) 313; X32-SSE2-NEXT: calll __umoddi3 314; X32-SSE2-NEXT: addl $16, %esp 315; X32-SSE2-NEXT: movl %eax, %edx 316; X32-SSE2-NEXT: movl %edx, %ecx 317; X32-SSE2-NEXT: notb %cl 318; X32-SSE2-NEXT: shrdl %cl, %edi, %ebx 319; X32-SSE2-NEXT: shrl %cl, %edi 320; X32-SSE2-NEXT: xorl %eax, %eax 321; X32-SSE2-NEXT: testb $32, %cl 322; X32-SSE2-NEXT: cmovnel %edi, %ebx 323; X32-SSE2-NEXT: cmovnel %eax, %edi 324; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 325; X32-SSE2-NEXT: movl %edx, %ecx 326; X32-SSE2-NEXT: shll %cl, %eax 327; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebp 328; X32-SSE2-NEXT: shldl %cl, %ebp, %esi 329; X32-SSE2-NEXT: testb $32, %dl 330; X32-SSE2-NEXT: cmovnel %eax, %esi 331; X32-SSE2-NEXT: movl $0, %ecx 332; X32-SSE2-NEXT: cmovnel %ecx, %eax 333; X32-SSE2-NEXT: orl %ebx, %eax 334; X32-SSE2-NEXT: orl %edi, %esi 335; X32-SSE2-NEXT: movl %esi, %edx 336; X32-SSE2-NEXT: popl %esi 337; X32-SSE2-NEXT: popl %edi 338; X32-SSE2-NEXT: popl %ebx 339; X32-SSE2-NEXT: popl %ebp 340; X32-SSE2-NEXT: retl 341; 342; X64-AVX2-LABEL: fshl_i37: 343; X64-AVX2: # %bb.0: 344; X64-AVX2-NEXT: movq %rdx, %rcx 345; X64-AVX2-NEXT: movabsq $-2492803253203993461, %rdx # imm = 0xDD67C8A60DD67C8B 346; X64-AVX2-NEXT: movq %rcx, %rax 347; X64-AVX2-NEXT: mulq %rdx 348; X64-AVX2-NEXT: shrq $5, %rdx 349; X64-AVX2-NEXT: leal (%rdx,%rdx,8), %eax 350; X64-AVX2-NEXT: leal (%rdx,%rax,4), %eax 351; X64-AVX2-NEXT: subl %eax, %ecx 352; X64-AVX2-NEXT: shlq $27, %rsi 353; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $rcx 354; X64-AVX2-NEXT: shldq %cl, %rsi, %rdi 355; X64-AVX2-NEXT: movq %rdi, %rax 356; X64-AVX2-NEXT: retq 357 %f = call i37 @llvm.fshl.i37(i37 %x, i37 %y, i37 %z) 358 ret i37 %f 359} 360 361; extract(concat(0b1110000, 0b1111111) << 2) = 0b1000011 362 363declare i7 @llvm.fshl.i7(i7, i7, i7) 364define i7 @fshl_i7_const_fold() { 365; ANY-LABEL: fshl_i7_const_fold: 366; ANY: # %bb.0: 367; ANY-NEXT: movb $67, %al 368; ANY-NEXT: ret{{[l|q]}} 369 %f = call i7 @llvm.fshl.i7(i7 112, i7 127, i7 2) 370 ret i7 %f 371} 372 373; With constant shift amount, this is 'shld' with constant operand. 374 375define i32 @fshl_i32_const_shift(i32 %x, i32 %y) nounwind { 376; X32-SSE2-LABEL: fshl_i32_const_shift: 377; X32-SSE2: # %bb.0: 378; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 379; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 380; X32-SSE2-NEXT: shldl $9, %ecx, %eax 381; X32-SSE2-NEXT: retl 382; 383; X64-AVX2-LABEL: fshl_i32_const_shift: 384; X64-AVX2: # %bb.0: 385; X64-AVX2-NEXT: movl %edi, %eax 386; X64-AVX2-NEXT: shldl $9, %esi, %eax 387; X64-AVX2-NEXT: retq 388 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 9) 389 ret i32 %f 390} 391 392; Check modulo math on shift amount. 393 394define i32 @fshl_i32_const_overshift(i32 %x, i32 %y) nounwind { 395; X32-SSE2-LABEL: fshl_i32_const_overshift: 396; X32-SSE2: # %bb.0: 397; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 398; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 399; X32-SSE2-NEXT: shldl $9, %ecx, %eax 400; X32-SSE2-NEXT: retl 401; 402; X64-AVX2-LABEL: fshl_i32_const_overshift: 403; X64-AVX2: # %bb.0: 404; X64-AVX2-NEXT: movl %edi, %eax 405; X64-AVX2-NEXT: shldl $9, %esi, %eax 406; X64-AVX2-NEXT: retq 407 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 41) 408 ret i32 %f 409} 410 411; 64-bit should also work. 412 413define i64 @fshl_i64_const_overshift(i64 %x, i64 %y) nounwind { 414; X32-SSE2-LABEL: fshl_i64_const_overshift: 415; X32-SSE2: # %bb.0: 416; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 417; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 418; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 419; X32-SSE2-NEXT: shldl $9, %ecx, %edx 420; X32-SSE2-NEXT: shrdl $23, %ecx, %eax 421; X32-SSE2-NEXT: retl 422; 423; X64-AVX2-LABEL: fshl_i64_const_overshift: 424; X64-AVX2: # %bb.0: 425; X64-AVX2-NEXT: movq %rdi, %rax 426; X64-AVX2-NEXT: shldq $41, %rsi, %rax 427; X64-AVX2-NEXT: retq 428 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %y, i64 105) 429 ret i64 %f 430} 431 432; This should work without any node-specific logic. 433 434define i8 @fshl_i8_const_fold() nounwind { 435; ANY-LABEL: fshl_i8_const_fold: 436; ANY: # %bb.0: 437; ANY-NEXT: movb $-128, %al 438; ANY-NEXT: ret{{[l|q]}} 439 %f = call i8 @llvm.fshl.i8(i8 255, i8 0, i8 7) 440 ret i8 %f 441} 442 443; Repeat everything for funnel shift right. 444 445; General case - all operands can be variables 446 447define i32 @fshr_i32(i32 %x, i32 %y, i32 %z) nounwind { 448; X32-SSE2-LABEL: fshr_i32: 449; X32-SSE2: # %bb.0: 450; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 451; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 452; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 453; X32-SSE2-NEXT: shrdl %cl, %edx, %eax 454; X32-SSE2-NEXT: retl 455; 456; X64-AVX2-LABEL: fshr_i32: 457; X64-AVX2: # %bb.0: 458; X64-AVX2-NEXT: movl %edx, %ecx 459; X64-AVX2-NEXT: movl %esi, %eax 460; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 461; X64-AVX2-NEXT: shrdl %cl, %edi, %eax 462; X64-AVX2-NEXT: retq 463 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %z) 464 ret i32 %f 465} 466 467; Verify that weird types are minimally supported. 468declare i37 @llvm.fshr.i37(i37, i37, i37) 469define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) nounwind { 470; X32-SSE2-LABEL: fshr_i37: 471; X32-SSE2: # %bb.0: 472; X32-SSE2-NEXT: pushl %ebp 473; X32-SSE2-NEXT: pushl %ebx 474; X32-SSE2-NEXT: pushl %edi 475; X32-SSE2-NEXT: pushl %esi 476; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebp 477; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebx 478; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edi 479; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi 480; X32-SSE2-NEXT: shldl $1, %edi, %esi 481; X32-SSE2-NEXT: addl %edi, %edi 482; X32-SSE2-NEXT: pushl $0 483; X32-SSE2-NEXT: pushl $37 484; X32-SSE2-NEXT: pushl {{[0-9]+}}(%esp) 485; X32-SSE2-NEXT: pushl {{[0-9]+}}(%esp) 486; X32-SSE2-NEXT: calll __umoddi3 487; X32-SSE2-NEXT: addl $16, %esp 488; X32-SSE2-NEXT: movl %eax, %edx 489; X32-SSE2-NEXT: addb $27, %dl 490; X32-SSE2-NEXT: movl %edx, %eax 491; X32-SSE2-NEXT: notb %al 492; X32-SSE2-NEXT: movl %eax, %ecx 493; X32-SSE2-NEXT: shldl %cl, %edi, %esi 494; X32-SSE2-NEXT: shldl $27, %ebp, %ebx 495; X32-SSE2-NEXT: shll $27, %ebp 496; X32-SSE2-NEXT: movl %edx, %ecx 497; X32-SSE2-NEXT: shrdl %cl, %ebx, %ebp 498; X32-SSE2-NEXT: shrl %cl, %ebx 499; X32-SSE2-NEXT: xorl %ecx, %ecx 500; X32-SSE2-NEXT: testb $32, %dl 501; X32-SSE2-NEXT: cmovnel %ebx, %ebp 502; X32-SSE2-NEXT: cmovnel %ecx, %ebx 503; X32-SSE2-NEXT: xorl %edx, %edx 504; X32-SSE2-NEXT: movl %eax, %ecx 505; X32-SSE2-NEXT: shll %cl, %edi 506; X32-SSE2-NEXT: testb $32, %al 507; X32-SSE2-NEXT: cmovnel %edi, %esi 508; X32-SSE2-NEXT: cmovnel %edx, %edi 509; X32-SSE2-NEXT: orl %ebp, %edi 510; X32-SSE2-NEXT: orl %ebx, %esi 511; X32-SSE2-NEXT: movl %edi, %eax 512; X32-SSE2-NEXT: movl %esi, %edx 513; X32-SSE2-NEXT: popl %esi 514; X32-SSE2-NEXT: popl %edi 515; X32-SSE2-NEXT: popl %ebx 516; X32-SSE2-NEXT: popl %ebp 517; X32-SSE2-NEXT: retl 518; 519; X64-AVX2-LABEL: fshr_i37: 520; X64-AVX2: # %bb.0: 521; X64-AVX2-NEXT: movq %rdx, %rcx 522; X64-AVX2-NEXT: movabsq $-2492803253203993461, %rdx # imm = 0xDD67C8A60DD67C8B 523; X64-AVX2-NEXT: movq %rcx, %rax 524; X64-AVX2-NEXT: mulq %rdx 525; X64-AVX2-NEXT: shrq $5, %rdx 526; X64-AVX2-NEXT: leal (%rdx,%rdx,8), %eax 527; X64-AVX2-NEXT: leal (%rdx,%rax,4), %eax 528; X64-AVX2-NEXT: subl %eax, %ecx 529; X64-AVX2-NEXT: addl $27, %ecx 530; X64-AVX2-NEXT: shlq $27, %rsi 531; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $rcx 532; X64-AVX2-NEXT: shrdq %cl, %rdi, %rsi 533; X64-AVX2-NEXT: movq %rsi, %rax 534; X64-AVX2-NEXT: retq 535 %f = call i37 @llvm.fshr.i37(i37 %x, i37 %y, i37 %z) 536 ret i37 %f 537} 538 539; extract(concat(0b1110000, 0b1111111) >> 2) = 0b0011111 540 541declare i7 @llvm.fshr.i7(i7, i7, i7) 542define i7 @fshr_i7_const_fold() nounwind { 543; ANY-LABEL: fshr_i7_const_fold: 544; ANY: # %bb.0: 545; ANY-NEXT: movb $31, %al 546; ANY-NEXT: ret{{[l|q]}} 547 %f = call i7 @llvm.fshr.i7(i7 112, i7 127, i7 2) 548 ret i7 %f 549} 550 551; demanded bits tests 552 553define i32 @fshl_i32_demandedbits(i32 %a0, i32 %a1) nounwind { 554; X32-SSE2-LABEL: fshl_i32_demandedbits: 555; X32-SSE2: # %bb.0: 556; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 557; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 558; X32-SSE2-NEXT: shldl $9, %ecx, %eax 559; X32-SSE2-NEXT: retl 560; 561; X64-AVX2-LABEL: fshl_i32_demandedbits: 562; X64-AVX2: # %bb.0: 563; X64-AVX2-NEXT: movl %edi, %eax 564; X64-AVX2-NEXT: shldl $9, %esi, %eax 565; X64-AVX2-NEXT: retq 566 %x = or i32 %a0, 2147483648 567 %y = or i32 %a1, 1 568 %res = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 9) 569 ret i32 %res 570} 571 572define i32 @fshr_i32_demandedbits(i32 %a0, i32 %a1) nounwind { 573; X32-SSE2-LABEL: fshr_i32_demandedbits: 574; X32-SSE2: # %bb.0: 575; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 576; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 577; X32-SSE2-NEXT: shrdl $9, %ecx, %eax 578; X32-SSE2-NEXT: retl 579; 580; X64-AVX2-LABEL: fshr_i32_demandedbits: 581; X64-AVX2: # %bb.0: 582; X64-AVX2-NEXT: movl %edi, %eax 583; X64-AVX2-NEXT: shldl $23, %esi, %eax 584; X64-AVX2-NEXT: retq 585 %x = or i32 %a0, 2147483648 586 %y = or i32 %a1, 1 587 %res = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 9) 588 ret i32 %res 589} 590 591; undef handling 592 593define i32 @fshl_i32_undef0(i32 %a0, i32 %a1) nounwind { 594; X32-SSE2-LABEL: fshl_i32_undef0: 595; X32-SSE2: # %bb.0: 596; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 597; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 598; X32-SSE2-NEXT: shldl %cl, %eax, %eax 599; X32-SSE2-NEXT: retl 600; 601; X64-AVX2-LABEL: fshl_i32_undef0: 602; X64-AVX2: # %bb.0: 603; X64-AVX2-NEXT: movl %esi, %ecx 604; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 605; X64-AVX2-NEXT: shldl %cl, %edi, %eax 606; X64-AVX2-NEXT: retq 607 %res = call i32 @llvm.fshl.i32(i32 undef, i32 %a0, i32 %a1) 608 ret i32 %res 609} 610 611define i32 @fshl_i32_undef0_msk(i32 %a0, i32 %a1) nounwind { 612; X32-SSE2-LABEL: fshl_i32_undef0_msk: 613; X32-SSE2: # %bb.0: 614; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 615; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 616; X32-SSE2-NEXT: andl $7, %ecx 617; X32-SSE2-NEXT: # kill: def $cl killed $cl killed $ecx 618; X32-SSE2-NEXT: shldl %cl, %eax, %eax 619; X32-SSE2-NEXT: retl 620; 621; X64-AVX2-LABEL: fshl_i32_undef0_msk: 622; X64-AVX2: # %bb.0: 623; X64-AVX2-NEXT: movl %esi, %ecx 624; X64-AVX2-NEXT: andl $7, %ecx 625; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 626; X64-AVX2-NEXT: shldl %cl, %edi, %eax 627; X64-AVX2-NEXT: retq 628 %m = and i32 %a1, 7 629 %res = call i32 @llvm.fshl.i32(i32 undef, i32 %a0, i32 %m) 630 ret i32 %res 631} 632 633define i32 @fshl_i32_undef0_cst(i32 %a0) nounwind { 634; X32-SSE2-LABEL: fshl_i32_undef0_cst: 635; X32-SSE2: # %bb.0: 636; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 637; X32-SSE2-NEXT: shrl $23, %eax 638; X32-SSE2-NEXT: retl 639; 640; X64-AVX2-LABEL: fshl_i32_undef0_cst: 641; X64-AVX2: # %bb.0: 642; X64-AVX2-NEXT: movl %edi, %eax 643; X64-AVX2-NEXT: shrl $23, %eax 644; X64-AVX2-NEXT: retq 645 %res = call i32 @llvm.fshl.i32(i32 undef, i32 %a0, i32 9) 646 ret i32 %res 647} 648 649define i32 @fshl_i32_undef1(i32 %a0, i32 %a1) nounwind { 650; X32-SSE2-LABEL: fshl_i32_undef1: 651; X32-SSE2: # %bb.0: 652; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 653; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 654; X32-SSE2-NEXT: shldl %cl, %eax, %eax 655; X32-SSE2-NEXT: retl 656; 657; X64-AVX2-LABEL: fshl_i32_undef1: 658; X64-AVX2: # %bb.0: 659; X64-AVX2-NEXT: movl %esi, %ecx 660; X64-AVX2-NEXT: movl %edi, %eax 661; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 662; X64-AVX2-NEXT: shldl %cl, %eax, %eax 663; X64-AVX2-NEXT: retq 664 %res = call i32 @llvm.fshl.i32(i32 %a0, i32 undef, i32 %a1) 665 ret i32 %res 666} 667 668define i32 @fshl_i32_undef1_msk(i32 %a0, i32 %a1) nounwind { 669; X32-SSE2-LABEL: fshl_i32_undef1_msk: 670; X32-SSE2: # %bb.0: 671; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 672; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 673; X32-SSE2-NEXT: andb $7, %cl 674; X32-SSE2-NEXT: shll %cl, %eax 675; X32-SSE2-NEXT: retl 676; 677; X64-AVX2-LABEL: fshl_i32_undef1_msk: 678; X64-AVX2: # %bb.0: 679; X64-AVX2-NEXT: movl %esi, %ecx 680; X64-AVX2-NEXT: movl %edi, %eax 681; X64-AVX2-NEXT: andb $7, %cl 682; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 683; X64-AVX2-NEXT: shll %cl, %eax 684; X64-AVX2-NEXT: retq 685 %m = and i32 %a1, 7 686 %res = call i32 @llvm.fshl.i32(i32 %a0, i32 undef, i32 %m) 687 ret i32 %res 688} 689 690define i32 @fshl_i32_undef1_cst(i32 %a0) nounwind { 691; X32-SSE2-LABEL: fshl_i32_undef1_cst: 692; X32-SSE2: # %bb.0: 693; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 694; X32-SSE2-NEXT: shll $9, %eax 695; X32-SSE2-NEXT: retl 696; 697; X64-AVX2-LABEL: fshl_i32_undef1_cst: 698; X64-AVX2: # %bb.0: 699; X64-AVX2-NEXT: movl %edi, %eax 700; X64-AVX2-NEXT: shll $9, %eax 701; X64-AVX2-NEXT: retq 702 %res = call i32 @llvm.fshl.i32(i32 %a0, i32 undef, i32 9) 703 ret i32 %res 704} 705 706define i32 @fshl_i32_undef2(i32 %a0, i32 %a1) nounwind { 707; X32-SSE2-LABEL: fshl_i32_undef2: 708; X32-SSE2: # %bb.0: 709; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 710; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 711; X32-SSE2-NEXT: shldl %cl, %ecx, %eax 712; X32-SSE2-NEXT: retl 713; 714; X64-AVX2-LABEL: fshl_i32_undef2: 715; X64-AVX2: # %bb.0: 716; X64-AVX2-NEXT: movl %edi, %eax 717; X64-AVX2-NEXT: shldl %cl, %esi, %eax 718; X64-AVX2-NEXT: retq 719 %res = call i32 @llvm.fshl.i32(i32 %a0, i32 %a1, i32 undef) 720 ret i32 %res 721} 722 723define i32 @fshr_i32_undef0(i32 %a0, i32 %a1) nounwind { 724; X32-SSE2-LABEL: fshr_i32_undef0: 725; X32-SSE2: # %bb.0: 726; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 727; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 728; X32-SSE2-NEXT: shrdl %cl, %eax, %eax 729; X32-SSE2-NEXT: retl 730; 731; X64-AVX2-LABEL: fshr_i32_undef0: 732; X64-AVX2: # %bb.0: 733; X64-AVX2-NEXT: movl %esi, %ecx 734; X64-AVX2-NEXT: movl %edi, %eax 735; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 736; X64-AVX2-NEXT: shrdl %cl, %eax, %eax 737; X64-AVX2-NEXT: retq 738 %res = call i32 @llvm.fshr.i32(i32 undef, i32 %a0, i32 %a1) 739 ret i32 %res 740} 741 742define i32 @fshr_i32_undef0_msk(i32 %a0, i32 %a1) nounwind { 743; X32-SSE2-LABEL: fshr_i32_undef0_msk: 744; X32-SSE2: # %bb.0: 745; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 746; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 747; X32-SSE2-NEXT: andb $7, %cl 748; X32-SSE2-NEXT: shrl %cl, %eax 749; X32-SSE2-NEXT: retl 750; 751; X64-AVX2-LABEL: fshr_i32_undef0_msk: 752; X64-AVX2: # %bb.0: 753; X64-AVX2-NEXT: movl %esi, %ecx 754; X64-AVX2-NEXT: movl %edi, %eax 755; X64-AVX2-NEXT: andb $7, %cl 756; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 757; X64-AVX2-NEXT: shrl %cl, %eax 758; X64-AVX2-NEXT: retq 759 %m = and i32 %a1, 7 760 %res = call i32 @llvm.fshr.i32(i32 undef, i32 %a0, i32 %m) 761 ret i32 %res 762} 763 764define i32 @fshr_i32_undef0_cst(i32 %a0) nounwind { 765; X32-SSE2-LABEL: fshr_i32_undef0_cst: 766; X32-SSE2: # %bb.0: 767; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 768; X32-SSE2-NEXT: shrl $9, %eax 769; X32-SSE2-NEXT: retl 770; 771; X64-AVX2-LABEL: fshr_i32_undef0_cst: 772; X64-AVX2: # %bb.0: 773; X64-AVX2-NEXT: movl %edi, %eax 774; X64-AVX2-NEXT: shrl $9, %eax 775; X64-AVX2-NEXT: retq 776 %res = call i32 @llvm.fshr.i32(i32 undef, i32 %a0, i32 9) 777 ret i32 %res 778} 779 780define i32 @fshr_i32_undef1(i32 %a0, i32 %a1) nounwind { 781; X32-SSE2-LABEL: fshr_i32_undef1: 782; X32-SSE2: # %bb.0: 783; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 784; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 785; X32-SSE2-NEXT: shrdl %cl, %eax, %eax 786; X32-SSE2-NEXT: retl 787; 788; X64-AVX2-LABEL: fshr_i32_undef1: 789; X64-AVX2: # %bb.0: 790; X64-AVX2-NEXT: movl %esi, %ecx 791; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 792; X64-AVX2-NEXT: shrdl %cl, %edi, %eax 793; X64-AVX2-NEXT: retq 794 %res = call i32 @llvm.fshr.i32(i32 %a0, i32 undef, i32 %a1) 795 ret i32 %res 796} 797 798define i32 @fshr_i32_undef1_msk(i32 %a0, i32 %a1) nounwind { 799; X32-SSE2-LABEL: fshr_i32_undef1_msk: 800; X32-SSE2: # %bb.0: 801; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 802; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 803; X32-SSE2-NEXT: andl $7, %ecx 804; X32-SSE2-NEXT: # kill: def $cl killed $cl killed $ecx 805; X32-SSE2-NEXT: shrdl %cl, %eax, %eax 806; X32-SSE2-NEXT: retl 807; 808; X64-AVX2-LABEL: fshr_i32_undef1_msk: 809; X64-AVX2: # %bb.0: 810; X64-AVX2-NEXT: movl %esi, %ecx 811; X64-AVX2-NEXT: andl $7, %ecx 812; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 813; X64-AVX2-NEXT: shrdl %cl, %edi, %eax 814; X64-AVX2-NEXT: retq 815 %m = and i32 %a1, 7 816 %res = call i32 @llvm.fshr.i32(i32 %a0, i32 undef, i32 %m) 817 ret i32 %res 818} 819 820define i32 @fshr_i32_undef1_cst(i32 %a0) nounwind { 821; X32-SSE2-LABEL: fshr_i32_undef1_cst: 822; X32-SSE2: # %bb.0: 823; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 824; X32-SSE2-NEXT: shll $23, %eax 825; X32-SSE2-NEXT: retl 826; 827; X64-AVX2-LABEL: fshr_i32_undef1_cst: 828; X64-AVX2: # %bb.0: 829; X64-AVX2-NEXT: movl %edi, %eax 830; X64-AVX2-NEXT: shll $23, %eax 831; X64-AVX2-NEXT: retq 832 %res = call i32 @llvm.fshr.i32(i32 %a0, i32 undef, i32 9) 833 ret i32 %res 834} 835 836define i32 @fshr_i32_undef2(i32 %a0, i32 %a1) nounwind { 837; X32-SSE2-LABEL: fshr_i32_undef2: 838; X32-SSE2: # %bb.0: 839; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 840; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 841; X32-SSE2-NEXT: shrdl %cl, %ecx, %eax 842; X32-SSE2-NEXT: retl 843; 844; X64-AVX2-LABEL: fshr_i32_undef2: 845; X64-AVX2: # %bb.0: 846; X64-AVX2-NEXT: movl %esi, %eax 847; X64-AVX2-NEXT: shrdl %cl, %edi, %eax 848; X64-AVX2-NEXT: retq 849 %res = call i32 @llvm.fshr.i32(i32 %a0, i32 %a1, i32 undef) 850 ret i32 %res 851} 852 853; shift zero args 854 855define i32 @fshl_i32_zero0(i32 %a0, i32 %a1) nounwind { 856; X32-SSE2-LABEL: fshl_i32_zero0: 857; X32-SSE2: # %bb.0: 858; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 859; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 860; X32-SSE2-NEXT: xorl %eax, %eax 861; X32-SSE2-NEXT: shldl %cl, %edx, %eax 862; X32-SSE2-NEXT: retl 863; 864; X64-AVX2-LABEL: fshl_i32_zero0: 865; X64-AVX2: # %bb.0: 866; X64-AVX2-NEXT: movl %esi, %ecx 867; X64-AVX2-NEXT: xorl %eax, %eax 868; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 869; X64-AVX2-NEXT: shldl %cl, %edi, %eax 870; X64-AVX2-NEXT: retq 871 %res = call i32 @llvm.fshl.i32(i32 0, i32 %a0, i32 %a1) 872 ret i32 %res 873} 874 875define i32 @fshl_i32_zero0_cst(i32 %a0) nounwind { 876; X32-SSE2-LABEL: fshl_i32_zero0_cst: 877; X32-SSE2: # %bb.0: 878; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 879; X32-SSE2-NEXT: shrl $23, %eax 880; X32-SSE2-NEXT: retl 881; 882; X64-AVX2-LABEL: fshl_i32_zero0_cst: 883; X64-AVX2: # %bb.0: 884; X64-AVX2-NEXT: movl %edi, %eax 885; X64-AVX2-NEXT: shrl $23, %eax 886; X64-AVX2-NEXT: retq 887 %res = call i32 @llvm.fshl.i32(i32 0, i32 %a0, i32 9) 888 ret i32 %res 889} 890 891define i32 @fshl_i32_zero1(i32 %a0, i32 %a1) nounwind { 892; X32-SSE2-LABEL: fshl_i32_zero1: 893; X32-SSE2: # %bb.0: 894; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 895; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 896; X32-SSE2-NEXT: xorl %edx, %edx 897; X32-SSE2-NEXT: shldl %cl, %edx, %eax 898; X32-SSE2-NEXT: retl 899; 900; X64-AVX2-LABEL: fshl_i32_zero1: 901; X64-AVX2: # %bb.0: 902; X64-AVX2-NEXT: movl %esi, %ecx 903; X64-AVX2-NEXT: movl %edi, %eax 904; X64-AVX2-NEXT: xorl %edx, %edx 905; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 906; X64-AVX2-NEXT: shldl %cl, %edx, %eax 907; X64-AVX2-NEXT: retq 908 %res = call i32 @llvm.fshl.i32(i32 %a0, i32 0, i32 %a1) 909 ret i32 %res 910} 911 912define i32 @fshl_i32_zero1_cst(i32 %a0) nounwind { 913; X32-SSE2-LABEL: fshl_i32_zero1_cst: 914; X32-SSE2: # %bb.0: 915; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 916; X32-SSE2-NEXT: shll $9, %eax 917; X32-SSE2-NEXT: retl 918; 919; X64-AVX2-LABEL: fshl_i32_zero1_cst: 920; X64-AVX2: # %bb.0: 921; X64-AVX2-NEXT: movl %edi, %eax 922; X64-AVX2-NEXT: shll $9, %eax 923; X64-AVX2-NEXT: retq 924 %res = call i32 @llvm.fshl.i32(i32 %a0, i32 0, i32 9) 925 ret i32 %res 926} 927 928define i32 @fshr_i32_zero0(i32 %a0, i32 %a1) nounwind { 929; X32-SSE2-LABEL: fshr_i32_zero0: 930; X32-SSE2: # %bb.0: 931; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 932; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 933; X32-SSE2-NEXT: xorl %edx, %edx 934; X32-SSE2-NEXT: shrdl %cl, %edx, %eax 935; X32-SSE2-NEXT: retl 936; 937; X64-AVX2-LABEL: fshr_i32_zero0: 938; X64-AVX2: # %bb.0: 939; X64-AVX2-NEXT: movl %esi, %ecx 940; X64-AVX2-NEXT: movl %edi, %eax 941; X64-AVX2-NEXT: xorl %edx, %edx 942; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 943; X64-AVX2-NEXT: shrdl %cl, %edx, %eax 944; X64-AVX2-NEXT: retq 945 %res = call i32 @llvm.fshr.i32(i32 0, i32 %a0, i32 %a1) 946 ret i32 %res 947} 948 949define i32 @fshr_i32_zero0_cst(i32 %a0) nounwind { 950; X32-SSE2-LABEL: fshr_i32_zero0_cst: 951; X32-SSE2: # %bb.0: 952; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 953; X32-SSE2-NEXT: shrl $9, %eax 954; X32-SSE2-NEXT: retl 955; 956; X64-AVX2-LABEL: fshr_i32_zero0_cst: 957; X64-AVX2: # %bb.0: 958; X64-AVX2-NEXT: movl %edi, %eax 959; X64-AVX2-NEXT: shrl $9, %eax 960; X64-AVX2-NEXT: retq 961 %res = call i32 @llvm.fshr.i32(i32 0, i32 %a0, i32 9) 962 ret i32 %res 963} 964 965define i32 @fshr_i32_zero1(i32 %a0, i32 %a1) nounwind { 966; X32-SSE2-LABEL: fshr_i32_zero1: 967; X32-SSE2: # %bb.0: 968; X32-SSE2-NEXT: movb {{[0-9]+}}(%esp), %cl 969; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 970; X32-SSE2-NEXT: xorl %eax, %eax 971; X32-SSE2-NEXT: shrdl %cl, %edx, %eax 972; X32-SSE2-NEXT: retl 973; 974; X64-AVX2-LABEL: fshr_i32_zero1: 975; X64-AVX2: # %bb.0: 976; X64-AVX2-NEXT: movl %esi, %ecx 977; X64-AVX2-NEXT: xorl %eax, %eax 978; X64-AVX2-NEXT: # kill: def $cl killed $cl killed $ecx 979; X64-AVX2-NEXT: shrdl %cl, %edi, %eax 980; X64-AVX2-NEXT: retq 981 %res = call i32 @llvm.fshr.i32(i32 %a0, i32 0, i32 %a1) 982 ret i32 %res 983} 984 985define i32 @fshr_i32_zero1_cst(i32 %a0) nounwind { 986; X32-SSE2-LABEL: fshr_i32_zero1_cst: 987; X32-SSE2: # %bb.0: 988; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 989; X32-SSE2-NEXT: shll $23, %eax 990; X32-SSE2-NEXT: retl 991; 992; X64-AVX2-LABEL: fshr_i32_zero1_cst: 993; X64-AVX2: # %bb.0: 994; X64-AVX2-NEXT: movl %edi, %eax 995; X64-AVX2-NEXT: shll $23, %eax 996; X64-AVX2-NEXT: retq 997 %res = call i32 @llvm.fshr.i32(i32 %a0, i32 0, i32 9) 998 ret i32 %res 999} 1000 1001; shift by zero 1002 1003define i32 @fshl_i32_zero2(i32 %a0, i32 %a1) nounwind { 1004; X32-SSE2-LABEL: fshl_i32_zero2: 1005; X32-SSE2: # %bb.0: 1006; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1007; X32-SSE2-NEXT: retl 1008; 1009; X64-AVX2-LABEL: fshl_i32_zero2: 1010; X64-AVX2: # %bb.0: 1011; X64-AVX2-NEXT: movl %edi, %eax 1012; X64-AVX2-NEXT: retq 1013 %res = call i32 @llvm.fshl.i32(i32 %a0, i32 %a1, i32 0) 1014 ret i32 %res 1015} 1016 1017define i32 @fshr_i32_zero2(i32 %a0, i32 %a1) nounwind { 1018; X32-SSE2-LABEL: fshr_i32_zero2: 1019; X32-SSE2: # %bb.0: 1020; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1021; X32-SSE2-NEXT: retl 1022; 1023; X64-AVX2-LABEL: fshr_i32_zero2: 1024; X64-AVX2: # %bb.0: 1025; X64-AVX2-NEXT: movl %esi, %eax 1026; X64-AVX2-NEXT: retq 1027 %res = call i32 @llvm.fshr.i32(i32 %a0, i32 %a1, i32 0) 1028 ret i32 %res 1029} 1030 1031; With constant shift amount, this is 'shrd' or 'shld'. 1032 1033define i32 @fshr_i32_const_shift(i32 %x, i32 %y) nounwind { 1034; X32-SSE2-LABEL: fshr_i32_const_shift: 1035; X32-SSE2: # %bb.0: 1036; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 1037; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1038; X32-SSE2-NEXT: shrdl $9, %ecx, %eax 1039; X32-SSE2-NEXT: retl 1040; 1041; X64-AVX2-LABEL: fshr_i32_const_shift: 1042; X64-AVX2: # %bb.0: 1043; X64-AVX2-NEXT: movl %edi, %eax 1044; X64-AVX2-NEXT: shldl $23, %esi, %eax 1045; X64-AVX2-NEXT: retq 1046 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 9) 1047 ret i32 %f 1048} 1049 1050; Check modulo math on shift amount. 41-32=9, but right-shift may became left, so 32-9=23. 1051 1052define i32 @fshr_i32_const_overshift(i32 %x, i32 %y) nounwind { 1053; X32-SSE2-LABEL: fshr_i32_const_overshift: 1054; X32-SSE2: # %bb.0: 1055; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 1056; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1057; X32-SSE2-NEXT: shrdl $9, %ecx, %eax 1058; X32-SSE2-NEXT: retl 1059; 1060; X64-AVX2-LABEL: fshr_i32_const_overshift: 1061; X64-AVX2: # %bb.0: 1062; X64-AVX2-NEXT: movl %edi, %eax 1063; X64-AVX2-NEXT: shldl $23, %esi, %eax 1064; X64-AVX2-NEXT: retq 1065 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 41) 1066 ret i32 %f 1067} 1068 1069; 64-bit should also work. 105-64 = 41, but right-shift became left, so 64-41=23. 1070 1071define i64 @fshr_i64_const_overshift(i64 %x, i64 %y) nounwind { 1072; X32-SSE2-LABEL: fshr_i64_const_overshift: 1073; X32-SSE2: # %bb.0: 1074; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1075; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx 1076; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx 1077; X32-SSE2-NEXT: shrdl $9, %ecx, %eax 1078; X32-SSE2-NEXT: shldl $23, %ecx, %edx 1079; X32-SSE2-NEXT: retl 1080; 1081; X64-AVX2-LABEL: fshr_i64_const_overshift: 1082; X64-AVX2: # %bb.0: 1083; X64-AVX2-NEXT: movq %rdi, %rax 1084; X64-AVX2-NEXT: shldq $23, %rsi, %rax 1085; X64-AVX2-NEXT: retq 1086 %f = call i64 @llvm.fshr.i64(i64 %x, i64 %y, i64 105) 1087 ret i64 %f 1088} 1089 1090; This should work without any node-specific logic. 1091 1092define i8 @fshr_i8_const_fold() nounwind { 1093; ANY-LABEL: fshr_i8_const_fold: 1094; ANY: # %bb.0: 1095; ANY-NEXT: movb $-2, %al 1096; ANY-NEXT: ret{{[l|q]}} 1097 %f = call i8 @llvm.fshr.i8(i8 255, i8 0, i8 7) 1098 ret i8 %f 1099} 1100 1101define i32 @fshl_i32_shift_by_bitwidth(i32 %x, i32 %y) nounwind { 1102; X32-SSE2-LABEL: fshl_i32_shift_by_bitwidth: 1103; X32-SSE2: # %bb.0: 1104; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1105; X32-SSE2-NEXT: retl 1106; 1107; X64-AVX2-LABEL: fshl_i32_shift_by_bitwidth: 1108; X64-AVX2: # %bb.0: 1109; X64-AVX2-NEXT: movl %edi, %eax 1110; X64-AVX2-NEXT: retq 1111 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 32) 1112 ret i32 %f 1113} 1114 1115define i32 @fshr_i32_shift_by_bitwidth(i32 %x, i32 %y) nounwind { 1116; X32-SSE2-LABEL: fshr_i32_shift_by_bitwidth: 1117; X32-SSE2: # %bb.0: 1118; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1119; X32-SSE2-NEXT: retl 1120; 1121; X64-AVX2-LABEL: fshr_i32_shift_by_bitwidth: 1122; X64-AVX2: # %bb.0: 1123; X64-AVX2-NEXT: movl %esi, %eax 1124; X64-AVX2-NEXT: retq 1125 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 32) 1126 ret i32 %f 1127} 1128 1129define <4 x i32> @fshl_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) nounwind { 1130; ANY-LABEL: fshl_v4i32_shift_by_bitwidth: 1131; ANY: # %bb.0: 1132; ANY-NEXT: ret{{[l|q]}} 1133 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 32, i32 32, i32 32, i32 32>) 1134 ret <4 x i32> %f 1135} 1136 1137define <4 x i32> @fshr_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) nounwind { 1138; X32-SSE2-LABEL: fshr_v4i32_shift_by_bitwidth: 1139; X32-SSE2: # %bb.0: 1140; X32-SSE2-NEXT: movaps %xmm1, %xmm0 1141; X32-SSE2-NEXT: retl 1142; 1143; X64-AVX2-LABEL: fshr_v4i32_shift_by_bitwidth: 1144; X64-AVX2: # %bb.0: 1145; X64-AVX2-NEXT: vmovaps %xmm1, %xmm0 1146; X64-AVX2-NEXT: retq 1147 %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 32, i32 32, i32 32, i32 32>) 1148 ret <4 x i32> %f 1149} 1150 1151%struct.S = type { [11 x i8], i8 } 1152define void @PR45265(i32 %0, %struct.S* nocapture readonly %1) nounwind { 1153; X32-SSE2-LABEL: PR45265: 1154; X32-SSE2: # %bb.0: 1155; X32-SSE2-NEXT: pushl %ebx 1156; X32-SSE2-NEXT: pushl %edi 1157; X32-SSE2-NEXT: pushl %esi 1158; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax 1159; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi 1160; X32-SSE2-NEXT: leal (%eax,%eax,2), %edi 1161; X32-SSE2-NEXT: movzwl 8(%esi,%edi,4), %ebx 1162; X32-SSE2-NEXT: movsbl 10(%esi,%edi,4), %ecx 1163; X32-SSE2-NEXT: movl %ecx, %edx 1164; X32-SSE2-NEXT: shll $16, %edx 1165; X32-SSE2-NEXT: orl %ebx, %edx 1166; X32-SSE2-NEXT: movl 4(%esi,%edi,4), %esi 1167; X32-SSE2-NEXT: shrdl $8, %edx, %esi 1168; X32-SSE2-NEXT: xorl %eax, %esi 1169; X32-SSE2-NEXT: sarl $31, %eax 1170; X32-SSE2-NEXT: sarl $31, %ecx 1171; X32-SSE2-NEXT: shldl $24, %edx, %ecx 1172; X32-SSE2-NEXT: xorl %eax, %ecx 1173; X32-SSE2-NEXT: orl %ecx, %esi 1174; X32-SSE2-NEXT: jne .LBB46_1 1175; X32-SSE2-NEXT: # %bb.2: 1176; X32-SSE2-NEXT: popl %esi 1177; X32-SSE2-NEXT: popl %edi 1178; X32-SSE2-NEXT: popl %ebx 1179; X32-SSE2-NEXT: jmp _Z3foov # TAILCALL 1180; X32-SSE2-NEXT: .LBB46_1: 1181; X32-SSE2-NEXT: popl %esi 1182; X32-SSE2-NEXT: popl %edi 1183; X32-SSE2-NEXT: popl %ebx 1184; X32-SSE2-NEXT: retl 1185; 1186; X64-AVX2-LABEL: PR45265: 1187; X64-AVX2: # %bb.0: 1188; X64-AVX2-NEXT: movslq %edi, %rax 1189; X64-AVX2-NEXT: leaq (%rax,%rax,2), %rcx 1190; X64-AVX2-NEXT: movsbq 10(%rsi,%rcx,4), %rdx 1191; X64-AVX2-NEXT: shlq $16, %rdx 1192; X64-AVX2-NEXT: movzwl 8(%rsi,%rcx,4), %edi 1193; X64-AVX2-NEXT: orq %rdx, %rdi 1194; X64-AVX2-NEXT: movq (%rsi,%rcx,4), %rcx 1195; X64-AVX2-NEXT: shrdq $40, %rdi, %rcx 1196; X64-AVX2-NEXT: cmpq %rax, %rcx 1197; X64-AVX2-NEXT: jne .LBB46_1 1198; X64-AVX2-NEXT: # %bb.2: 1199; X64-AVX2-NEXT: jmp _Z3foov # TAILCALL 1200; X64-AVX2-NEXT: .LBB46_1: 1201; X64-AVX2-NEXT: retq 1202 %3 = sext i32 %0 to i64 1203 %4 = getelementptr inbounds %struct.S, %struct.S* %1, i64 %3 1204 %5 = bitcast %struct.S* %4 to i88* 1205 %6 = load i88, i88* %5, align 1 1206 %7 = ashr i88 %6, 40 1207 %8 = trunc i88 %7 to i64 1208 %9 = icmp eq i64 %8, %3 1209 br i1 %9, label %10, label %11 1210 121110: 1212 tail call void @_Z3foov() 1213 br label %11 1214 121511: 1216 ret void 1217} 1218declare dso_local void @_Z3foov() 1219