1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck %s -check-prefix=RV32I 4; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ 5; RUN: | FileCheck %s -check-prefix=RV64I 6; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f \ 7; RUN: -target-abi ilp32f < %s | FileCheck %s -check-prefix=RV32IF 8; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f -mattr=+d \ 9; RUN: -target-abi ilp32d < %s | FileCheck %s -check-prefix=RV32IFD 10; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+f -mattr=+d \ 11; RUN: -target-abi lp64d < %s | FileCheck %s -check-prefix=RV64IFD 12; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f \ 13; RUN: -mattr=+zfh -target-abi ilp32f < %s \ 14; RUN: | FileCheck %s -check-prefix=RV32IFZFH 15; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f -mattr=+d \ 16; RUN: -mattr=+zfh -target-abi ilp32d < %s \ 17; RUN: | FileCheck %s -check-prefix=RV32IFDZFH 18; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+f -mattr=+d \ 19; RUN: -mattr=+zfh -target-abi lp64d < %s \ 20; RUN: | FileCheck %s -check-prefix=RV64IFDZFH 21; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f \ 22; RUN: -mattr=+zfhmin -target-abi ilp32f < %s \ 23; RUN: | FileCheck %s -check-prefix=RV32IFZFHMIN 24; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f -mattr=+d \ 25; RUN: -mattr=+zfhmin -target-abi ilp32d < %s \ 26; RUN: | FileCheck %s -check-prefix=RV32IFDZFHMIN 27; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+f -mattr=+d \ 28; RUN: -mattr=+zfhmin -target-abi lp64d < %s \ 29; RUN: | FileCheck %s -check-prefix=RV64IFDZFHMIN 30; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+zdinx \ 31; RUN: -target-abi ilp32 < %s \ 32; RUN: | FileCheck %s -check-prefix=RV32IZDINX 33; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+zdinx \ 34; RUN: -target-abi lp64 < %s \ 35; RUN: | FileCheck %s -check-prefix=RV64IZDINX 36 37; Test fcopysign scenarios where the sign argument is casted to the type of the 38; magnitude argument. Those casts can be folded away by the DAGCombiner. 39 40declare double @llvm.copysign.f64(double, double) 41declare float @llvm.copysign.f32(float, float) 42declare half @llvm.copysign.f16(half, half) 43 44define double @fold_promote_d_s(double %a, float %b) nounwind { 45; RV32I-LABEL: fold_promote_d_s: 46; RV32I: # %bb.0: 47; RV32I-NEXT: lui a3, 524288 48; RV32I-NEXT: slli a1, a1, 1 49; RV32I-NEXT: and a2, a2, a3 50; RV32I-NEXT: srli a1, a1, 1 51; RV32I-NEXT: or a1, a1, a2 52; RV32I-NEXT: ret 53; 54; RV64I-LABEL: fold_promote_d_s: 55; RV64I: # %bb.0: 56; RV64I-NEXT: lui a2, 524288 57; RV64I-NEXT: slli a0, a0, 1 58; RV64I-NEXT: and a1, a1, a2 59; RV64I-NEXT: slli a1, a1, 32 60; RV64I-NEXT: srli a0, a0, 1 61; RV64I-NEXT: or a0, a0, a1 62; RV64I-NEXT: ret 63; 64; RV32IF-LABEL: fold_promote_d_s: 65; RV32IF: # %bb.0: 66; RV32IF-NEXT: fmv.x.w a2, fa0 67; RV32IF-NEXT: lui a3, 524288 68; RV32IF-NEXT: slli a1, a1, 1 69; RV32IF-NEXT: and a2, a2, a3 70; RV32IF-NEXT: srli a1, a1, 1 71; RV32IF-NEXT: or a1, a1, a2 72; RV32IF-NEXT: ret 73; 74; RV32IFD-LABEL: fold_promote_d_s: 75; RV32IFD: # %bb.0: 76; RV32IFD-NEXT: fcvt.d.s fa5, fa1 77; RV32IFD-NEXT: fsgnj.d fa0, fa0, fa5 78; RV32IFD-NEXT: ret 79; 80; RV64IFD-LABEL: fold_promote_d_s: 81; RV64IFD: # %bb.0: 82; RV64IFD-NEXT: fcvt.d.s fa5, fa1 83; RV64IFD-NEXT: fsgnj.d fa0, fa0, fa5 84; RV64IFD-NEXT: ret 85; 86; RV32IFZFH-LABEL: fold_promote_d_s: 87; RV32IFZFH: # %bb.0: 88; RV32IFZFH-NEXT: fmv.x.w a2, fa0 89; RV32IFZFH-NEXT: lui a3, 524288 90; RV32IFZFH-NEXT: slli a1, a1, 1 91; RV32IFZFH-NEXT: and a2, a2, a3 92; RV32IFZFH-NEXT: srli a1, a1, 1 93; RV32IFZFH-NEXT: or a1, a1, a2 94; RV32IFZFH-NEXT: ret 95; 96; RV32IFDZFH-LABEL: fold_promote_d_s: 97; RV32IFDZFH: # %bb.0: 98; RV32IFDZFH-NEXT: fcvt.d.s fa5, fa1 99; RV32IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5 100; RV32IFDZFH-NEXT: ret 101; 102; RV64IFDZFH-LABEL: fold_promote_d_s: 103; RV64IFDZFH: # %bb.0: 104; RV64IFDZFH-NEXT: fcvt.d.s fa5, fa1 105; RV64IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5 106; RV64IFDZFH-NEXT: ret 107; 108; RV32IFZFHMIN-LABEL: fold_promote_d_s: 109; RV32IFZFHMIN: # %bb.0: 110; RV32IFZFHMIN-NEXT: fmv.x.w a2, fa0 111; RV32IFZFHMIN-NEXT: lui a3, 524288 112; RV32IFZFHMIN-NEXT: slli a1, a1, 1 113; RV32IFZFHMIN-NEXT: and a2, a2, a3 114; RV32IFZFHMIN-NEXT: srli a1, a1, 1 115; RV32IFZFHMIN-NEXT: or a1, a1, a2 116; RV32IFZFHMIN-NEXT: ret 117; 118; RV32IFDZFHMIN-LABEL: fold_promote_d_s: 119; RV32IFDZFHMIN: # %bb.0: 120; RV32IFDZFHMIN-NEXT: fcvt.d.s fa5, fa1 121; RV32IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5 122; RV32IFDZFHMIN-NEXT: ret 123; 124; RV64IFDZFHMIN-LABEL: fold_promote_d_s: 125; RV64IFDZFHMIN: # %bb.0: 126; RV64IFDZFHMIN-NEXT: fcvt.d.s fa5, fa1 127; RV64IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5 128; RV64IFDZFHMIN-NEXT: ret 129; 130; RV32IZDINX-LABEL: fold_promote_d_s: 131; RV32IZDINX: # %bb.0: 132; RV32IZDINX-NEXT: fcvt.d.s a2, a2 133; RV32IZDINX-NEXT: fsgnj.d a0, a0, a2 134; RV32IZDINX-NEXT: ret 135; 136; RV64IZDINX-LABEL: fold_promote_d_s: 137; RV64IZDINX: # %bb.0: 138; RV64IZDINX-NEXT: fcvt.d.s a1, a1 139; RV64IZDINX-NEXT: fsgnj.d a0, a0, a1 140; RV64IZDINX-NEXT: ret 141 %c = fpext float %b to double 142 %t = call double @llvm.copysign.f64(double %a, double %c) 143 ret double %t 144} 145 146define double @fold_promote_d_h(double %a, half %b) nounwind { 147; RV32I-LABEL: fold_promote_d_h: 148; RV32I: # %bb.0: 149; RV32I-NEXT: lui a3, 8 150; RV32I-NEXT: slli a1, a1, 1 151; RV32I-NEXT: and a2, a2, a3 152; RV32I-NEXT: slli a2, a2, 16 153; RV32I-NEXT: srli a1, a1, 1 154; RV32I-NEXT: or a1, a1, a2 155; RV32I-NEXT: ret 156; 157; RV64I-LABEL: fold_promote_d_h: 158; RV64I: # %bb.0: 159; RV64I-NEXT: lui a2, 8 160; RV64I-NEXT: slli a0, a0, 1 161; RV64I-NEXT: and a1, a1, a2 162; RV64I-NEXT: slli a1, a1, 48 163; RV64I-NEXT: srli a0, a0, 1 164; RV64I-NEXT: or a0, a0, a1 165; RV64I-NEXT: ret 166; 167; RV32IF-LABEL: fold_promote_d_h: 168; RV32IF: # %bb.0: 169; RV32IF-NEXT: fmv.x.w a2, fa0 170; RV32IF-NEXT: lui a3, 8 171; RV32IF-NEXT: slli a1, a1, 1 172; RV32IF-NEXT: and a2, a2, a3 173; RV32IF-NEXT: slli a2, a2, 16 174; RV32IF-NEXT: srli a1, a1, 1 175; RV32IF-NEXT: or a1, a1, a2 176; RV32IF-NEXT: ret 177; 178; RV32IFD-LABEL: fold_promote_d_h: 179; RV32IFD: # %bb.0: 180; RV32IFD-NEXT: addi sp, sp, -16 181; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 182; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill 183; RV32IFD-NEXT: fmv.d fs0, fa0 184; RV32IFD-NEXT: fmv.s fa0, fa1 185; RV32IFD-NEXT: call __extendhfsf2 186; RV32IFD-NEXT: fcvt.d.s fa5, fa0 187; RV32IFD-NEXT: fsgnj.d fa0, fs0, fa5 188; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 189; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload 190; RV32IFD-NEXT: addi sp, sp, 16 191; RV32IFD-NEXT: ret 192; 193; RV64IFD-LABEL: fold_promote_d_h: 194; RV64IFD: # %bb.0: 195; RV64IFD-NEXT: addi sp, sp, -16 196; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 197; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill 198; RV64IFD-NEXT: fmv.d fs0, fa0 199; RV64IFD-NEXT: fmv.s fa0, fa1 200; RV64IFD-NEXT: call __extendhfsf2 201; RV64IFD-NEXT: fcvt.d.s fa5, fa0 202; RV64IFD-NEXT: fsgnj.d fa0, fs0, fa5 203; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 204; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload 205; RV64IFD-NEXT: addi sp, sp, 16 206; RV64IFD-NEXT: ret 207; 208; RV32IFZFH-LABEL: fold_promote_d_h: 209; RV32IFZFH: # %bb.0: 210; RV32IFZFH-NEXT: fmv.x.h a2, fa0 211; RV32IFZFH-NEXT: lui a3, 8 212; RV32IFZFH-NEXT: slli a1, a1, 1 213; RV32IFZFH-NEXT: and a2, a2, a3 214; RV32IFZFH-NEXT: slli a2, a2, 16 215; RV32IFZFH-NEXT: srli a1, a1, 1 216; RV32IFZFH-NEXT: or a1, a1, a2 217; RV32IFZFH-NEXT: ret 218; 219; RV32IFDZFH-LABEL: fold_promote_d_h: 220; RV32IFDZFH: # %bb.0: 221; RV32IFDZFH-NEXT: fcvt.d.h fa5, fa1 222; RV32IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5 223; RV32IFDZFH-NEXT: ret 224; 225; RV64IFDZFH-LABEL: fold_promote_d_h: 226; RV64IFDZFH: # %bb.0: 227; RV64IFDZFH-NEXT: fcvt.d.h fa5, fa1 228; RV64IFDZFH-NEXT: fsgnj.d fa0, fa0, fa5 229; RV64IFDZFH-NEXT: ret 230; 231; RV32IFZFHMIN-LABEL: fold_promote_d_h: 232; RV32IFZFHMIN: # %bb.0: 233; RV32IFZFHMIN-NEXT: fmv.x.h a2, fa0 234; RV32IFZFHMIN-NEXT: lui a3, 8 235; RV32IFZFHMIN-NEXT: slli a1, a1, 1 236; RV32IFZFHMIN-NEXT: and a2, a2, a3 237; RV32IFZFHMIN-NEXT: slli a2, a2, 16 238; RV32IFZFHMIN-NEXT: srli a1, a1, 1 239; RV32IFZFHMIN-NEXT: or a1, a1, a2 240; RV32IFZFHMIN-NEXT: ret 241; 242; RV32IFDZFHMIN-LABEL: fold_promote_d_h: 243; RV32IFDZFHMIN: # %bb.0: 244; RV32IFDZFHMIN-NEXT: fcvt.d.h fa5, fa1 245; RV32IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5 246; RV32IFDZFHMIN-NEXT: ret 247; 248; RV64IFDZFHMIN-LABEL: fold_promote_d_h: 249; RV64IFDZFHMIN: # %bb.0: 250; RV64IFDZFHMIN-NEXT: fcvt.d.h fa5, fa1 251; RV64IFDZFHMIN-NEXT: fsgnj.d fa0, fa0, fa5 252; RV64IFDZFHMIN-NEXT: ret 253; 254; RV32IZDINX-LABEL: fold_promote_d_h: 255; RV32IZDINX: # %bb.0: 256; RV32IZDINX-NEXT: addi sp, sp, -16 257; RV32IZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 258; RV32IZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 259; RV32IZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 260; RV32IZDINX-NEXT: mv s1, a1 261; RV32IZDINX-NEXT: mv s0, a0 262; RV32IZDINX-NEXT: mv a0, a2 263; RV32IZDINX-NEXT: call __extendhfsf2 264; RV32IZDINX-NEXT: fcvt.d.s a0, a0 265; RV32IZDINX-NEXT: fsgnj.d a0, s0, a0 266; RV32IZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 267; RV32IZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 268; RV32IZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 269; RV32IZDINX-NEXT: addi sp, sp, 16 270; RV32IZDINX-NEXT: ret 271; 272; RV64IZDINX-LABEL: fold_promote_d_h: 273; RV64IZDINX: # %bb.0: 274; RV64IZDINX-NEXT: addi sp, sp, -16 275; RV64IZDINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 276; RV64IZDINX-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 277; RV64IZDINX-NEXT: mv s0, a0 278; RV64IZDINX-NEXT: mv a0, a1 279; RV64IZDINX-NEXT: call __extendhfsf2 280; RV64IZDINX-NEXT: fcvt.d.s a0, a0 281; RV64IZDINX-NEXT: fsgnj.d a0, s0, a0 282; RV64IZDINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 283; RV64IZDINX-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 284; RV64IZDINX-NEXT: addi sp, sp, 16 285; RV64IZDINX-NEXT: ret 286 %c = fpext half %b to double 287 %t = call double @llvm.copysign.f64(double %a, double %c) 288 ret double %t 289} 290 291define float @fold_promote_f_h(float %a, half %b) nounwind { 292; RV32I-LABEL: fold_promote_f_h: 293; RV32I: # %bb.0: 294; RV32I-NEXT: lui a2, 8 295; RV32I-NEXT: slli a0, a0, 1 296; RV32I-NEXT: and a1, a1, a2 297; RV32I-NEXT: slli a1, a1, 16 298; RV32I-NEXT: srli a0, a0, 1 299; RV32I-NEXT: or a0, a0, a1 300; RV32I-NEXT: ret 301; 302; RV64I-LABEL: fold_promote_f_h: 303; RV64I: # %bb.0: 304; RV64I-NEXT: lui a2, 8 305; RV64I-NEXT: slli a0, a0, 33 306; RV64I-NEXT: and a1, a1, a2 307; RV64I-NEXT: slliw a1, a1, 16 308; RV64I-NEXT: srli a0, a0, 33 309; RV64I-NEXT: or a0, a0, a1 310; RV64I-NEXT: ret 311; 312; RV32IF-LABEL: fold_promote_f_h: 313; RV32IF: # %bb.0: 314; RV32IF-NEXT: addi sp, sp, -16 315; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 316; RV32IF-NEXT: fsw fs0, 8(sp) # 4-byte Folded Spill 317; RV32IF-NEXT: fmv.s fs0, fa0 318; RV32IF-NEXT: fmv.s fa0, fa1 319; RV32IF-NEXT: call __extendhfsf2 320; RV32IF-NEXT: fsgnj.s fa0, fs0, fa0 321; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 322; RV32IF-NEXT: flw fs0, 8(sp) # 4-byte Folded Reload 323; RV32IF-NEXT: addi sp, sp, 16 324; RV32IF-NEXT: ret 325; 326; RV32IFD-LABEL: fold_promote_f_h: 327; RV32IFD: # %bb.0: 328; RV32IFD-NEXT: addi sp, sp, -16 329; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 330; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill 331; RV32IFD-NEXT: fmv.s fs0, fa0 332; RV32IFD-NEXT: fmv.s fa0, fa1 333; RV32IFD-NEXT: call __extendhfsf2 334; RV32IFD-NEXT: fsgnj.s fa0, fs0, fa0 335; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 336; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload 337; RV32IFD-NEXT: addi sp, sp, 16 338; RV32IFD-NEXT: ret 339; 340; RV64IFD-LABEL: fold_promote_f_h: 341; RV64IFD: # %bb.0: 342; RV64IFD-NEXT: addi sp, sp, -16 343; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 344; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill 345; RV64IFD-NEXT: fmv.s fs0, fa0 346; RV64IFD-NEXT: fmv.s fa0, fa1 347; RV64IFD-NEXT: call __extendhfsf2 348; RV64IFD-NEXT: fsgnj.s fa0, fs0, fa0 349; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 350; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload 351; RV64IFD-NEXT: addi sp, sp, 16 352; RV64IFD-NEXT: ret 353; 354; RV32IFZFH-LABEL: fold_promote_f_h: 355; RV32IFZFH: # %bb.0: 356; RV32IFZFH-NEXT: fcvt.s.h fa5, fa1 357; RV32IFZFH-NEXT: fsgnj.s fa0, fa0, fa5 358; RV32IFZFH-NEXT: ret 359; 360; RV32IFDZFH-LABEL: fold_promote_f_h: 361; RV32IFDZFH: # %bb.0: 362; RV32IFDZFH-NEXT: fcvt.s.h fa5, fa1 363; RV32IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5 364; RV32IFDZFH-NEXT: ret 365; 366; RV64IFDZFH-LABEL: fold_promote_f_h: 367; RV64IFDZFH: # %bb.0: 368; RV64IFDZFH-NEXT: fcvt.s.h fa5, fa1 369; RV64IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5 370; RV64IFDZFH-NEXT: ret 371; 372; RV32IFZFHMIN-LABEL: fold_promote_f_h: 373; RV32IFZFHMIN: # %bb.0: 374; RV32IFZFHMIN-NEXT: fcvt.s.h fa5, fa1 375; RV32IFZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5 376; RV32IFZFHMIN-NEXT: ret 377; 378; RV32IFDZFHMIN-LABEL: fold_promote_f_h: 379; RV32IFDZFHMIN: # %bb.0: 380; RV32IFDZFHMIN-NEXT: fcvt.s.h fa5, fa1 381; RV32IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5 382; RV32IFDZFHMIN-NEXT: ret 383; 384; RV64IFDZFHMIN-LABEL: fold_promote_f_h: 385; RV64IFDZFHMIN: # %bb.0: 386; RV64IFDZFHMIN-NEXT: fcvt.s.h fa5, fa1 387; RV64IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5 388; RV64IFDZFHMIN-NEXT: ret 389; 390; RV32IZDINX-LABEL: fold_promote_f_h: 391; RV32IZDINX: # %bb.0: 392; RV32IZDINX-NEXT: addi sp, sp, -16 393; RV32IZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 394; RV32IZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 395; RV32IZDINX-NEXT: mv s0, a0 396; RV32IZDINX-NEXT: mv a0, a1 397; RV32IZDINX-NEXT: call __extendhfsf2 398; RV32IZDINX-NEXT: fsgnj.s a0, s0, a0 399; RV32IZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 400; RV32IZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 401; RV32IZDINX-NEXT: addi sp, sp, 16 402; RV32IZDINX-NEXT: ret 403; 404; RV64IZDINX-LABEL: fold_promote_f_h: 405; RV64IZDINX: # %bb.0: 406; RV64IZDINX-NEXT: addi sp, sp, -16 407; RV64IZDINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 408; RV64IZDINX-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 409; RV64IZDINX-NEXT: mv s0, a0 410; RV64IZDINX-NEXT: mv a0, a1 411; RV64IZDINX-NEXT: call __extendhfsf2 412; RV64IZDINX-NEXT: fsgnj.s a0, s0, a0 413; RV64IZDINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 414; RV64IZDINX-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 415; RV64IZDINX-NEXT: addi sp, sp, 16 416; RV64IZDINX-NEXT: ret 417 %c = fpext half %b to float 418 %t = call float @llvm.copysign.f32(float %a, float %c) 419 ret float %t 420} 421 422define float @fold_demote_s_d(float %a, double %b) nounwind { 423; RV32I-LABEL: fold_demote_s_d: 424; RV32I: # %bb.0: 425; RV32I-NEXT: lui a1, 524288 426; RV32I-NEXT: slli a0, a0, 1 427; RV32I-NEXT: and a1, a2, a1 428; RV32I-NEXT: srli a0, a0, 1 429; RV32I-NEXT: or a0, a0, a1 430; RV32I-NEXT: ret 431; 432; RV64I-LABEL: fold_demote_s_d: 433; RV64I: # %bb.0: 434; RV64I-NEXT: slli a0, a0, 33 435; RV64I-NEXT: srli a1, a1, 63 436; RV64I-NEXT: srli a0, a0, 33 437; RV64I-NEXT: slli a1, a1, 63 438; RV64I-NEXT: srli a1, a1, 32 439; RV64I-NEXT: or a0, a0, a1 440; RV64I-NEXT: ret 441; 442; RV32IF-LABEL: fold_demote_s_d: 443; RV32IF: # %bb.0: 444; RV32IF-NEXT: fmv.w.x fa5, a1 445; RV32IF-NEXT: fsgnj.s fa0, fa0, fa5 446; RV32IF-NEXT: ret 447; 448; RV32IFD-LABEL: fold_demote_s_d: 449; RV32IFD: # %bb.0: 450; RV32IFD-NEXT: fcvt.s.d fa5, fa1 451; RV32IFD-NEXT: fsgnj.s fa0, fa0, fa5 452; RV32IFD-NEXT: ret 453; 454; RV64IFD-LABEL: fold_demote_s_d: 455; RV64IFD: # %bb.0: 456; RV64IFD-NEXT: fcvt.s.d fa5, fa1 457; RV64IFD-NEXT: fsgnj.s fa0, fa0, fa5 458; RV64IFD-NEXT: ret 459; 460; RV32IFZFH-LABEL: fold_demote_s_d: 461; RV32IFZFH: # %bb.0: 462; RV32IFZFH-NEXT: fmv.w.x fa5, a1 463; RV32IFZFH-NEXT: fsgnj.s fa0, fa0, fa5 464; RV32IFZFH-NEXT: ret 465; 466; RV32IFDZFH-LABEL: fold_demote_s_d: 467; RV32IFDZFH: # %bb.0: 468; RV32IFDZFH-NEXT: fcvt.s.d fa5, fa1 469; RV32IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5 470; RV32IFDZFH-NEXT: ret 471; 472; RV64IFDZFH-LABEL: fold_demote_s_d: 473; RV64IFDZFH: # %bb.0: 474; RV64IFDZFH-NEXT: fcvt.s.d fa5, fa1 475; RV64IFDZFH-NEXT: fsgnj.s fa0, fa0, fa5 476; RV64IFDZFH-NEXT: ret 477; 478; RV32IFZFHMIN-LABEL: fold_demote_s_d: 479; RV32IFZFHMIN: # %bb.0: 480; RV32IFZFHMIN-NEXT: fmv.w.x fa5, a1 481; RV32IFZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5 482; RV32IFZFHMIN-NEXT: ret 483; 484; RV32IFDZFHMIN-LABEL: fold_demote_s_d: 485; RV32IFDZFHMIN: # %bb.0: 486; RV32IFDZFHMIN-NEXT: fcvt.s.d fa5, fa1 487; RV32IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5 488; RV32IFDZFHMIN-NEXT: ret 489; 490; RV64IFDZFHMIN-LABEL: fold_demote_s_d: 491; RV64IFDZFHMIN: # %bb.0: 492; RV64IFDZFHMIN-NEXT: fcvt.s.d fa5, fa1 493; RV64IFDZFHMIN-NEXT: fsgnj.s fa0, fa0, fa5 494; RV64IFDZFHMIN-NEXT: ret 495; 496; RV32IZDINX-LABEL: fold_demote_s_d: 497; RV32IZDINX: # %bb.0: 498; RV32IZDINX-NEXT: mv a3, a2 499; RV32IZDINX-NEXT: mv a2, a1 500; RV32IZDINX-NEXT: fcvt.s.d a1, a2 501; RV32IZDINX-NEXT: fsgnj.s a0, a0, a1 502; RV32IZDINX-NEXT: ret 503; 504; RV64IZDINX-LABEL: fold_demote_s_d: 505; RV64IZDINX: # %bb.0: 506; RV64IZDINX-NEXT: fcvt.s.d a1, a1 507; RV64IZDINX-NEXT: fsgnj.s a0, a0, a1 508; RV64IZDINX-NEXT: ret 509 %c = fptrunc double %b to float 510 %t = call float @llvm.copysign.f32(float %a, float %c) 511 ret float %t 512} 513 514define half @fold_demote_h_s(half %a, float %b) nounwind { 515; RV32I-LABEL: fold_demote_h_s: 516; RV32I: # %bb.0: 517; RV32I-NEXT: lui a2, 524288 518; RV32I-NEXT: slli a0, a0, 17 519; RV32I-NEXT: and a1, a1, a2 520; RV32I-NEXT: srli a1, a1, 16 521; RV32I-NEXT: srli a0, a0, 17 522; RV32I-NEXT: or a0, a0, a1 523; RV32I-NEXT: ret 524; 525; RV64I-LABEL: fold_demote_h_s: 526; RV64I: # %bb.0: 527; RV64I-NEXT: srliw a1, a1, 31 528; RV64I-NEXT: slli a0, a0, 49 529; RV64I-NEXT: slli a1, a1, 15 530; RV64I-NEXT: srli a0, a0, 49 531; RV64I-NEXT: or a0, a0, a1 532; RV64I-NEXT: ret 533; 534; RV32IF-LABEL: fold_demote_h_s: 535; RV32IF: # %bb.0: 536; RV32IF-NEXT: fmv.x.w a0, fa0 537; RV32IF-NEXT: fmv.x.w a1, fa1 538; RV32IF-NEXT: lui a2, 524288 539; RV32IF-NEXT: and a1, a1, a2 540; RV32IF-NEXT: slli a0, a0, 17 541; RV32IF-NEXT: srli a1, a1, 16 542; RV32IF-NEXT: srli a0, a0, 17 543; RV32IF-NEXT: or a0, a0, a1 544; RV32IF-NEXT: lui a1, 1048560 545; RV32IF-NEXT: or a0, a0, a1 546; RV32IF-NEXT: fmv.w.x fa0, a0 547; RV32IF-NEXT: ret 548; 549; RV32IFD-LABEL: fold_demote_h_s: 550; RV32IFD: # %bb.0: 551; RV32IFD-NEXT: fmv.x.w a0, fa0 552; RV32IFD-NEXT: fmv.x.w a1, fa1 553; RV32IFD-NEXT: lui a2, 524288 554; RV32IFD-NEXT: and a1, a1, a2 555; RV32IFD-NEXT: slli a0, a0, 17 556; RV32IFD-NEXT: srli a1, a1, 16 557; RV32IFD-NEXT: srli a0, a0, 17 558; RV32IFD-NEXT: or a0, a0, a1 559; RV32IFD-NEXT: lui a1, 1048560 560; RV32IFD-NEXT: or a0, a0, a1 561; RV32IFD-NEXT: fmv.w.x fa0, a0 562; RV32IFD-NEXT: ret 563; 564; RV64IFD-LABEL: fold_demote_h_s: 565; RV64IFD: # %bb.0: 566; RV64IFD-NEXT: fmv.x.w a0, fa0 567; RV64IFD-NEXT: fmv.x.w a1, fa1 568; RV64IFD-NEXT: lui a2, 524288 569; RV64IFD-NEXT: and a1, a1, a2 570; RV64IFD-NEXT: slli a0, a0, 49 571; RV64IFD-NEXT: srli a1, a1, 16 572; RV64IFD-NEXT: srli a0, a0, 49 573; RV64IFD-NEXT: or a0, a0, a1 574; RV64IFD-NEXT: lui a1, 1048560 575; RV64IFD-NEXT: or a0, a0, a1 576; RV64IFD-NEXT: fmv.w.x fa0, a0 577; RV64IFD-NEXT: ret 578; 579; RV32IFZFH-LABEL: fold_demote_h_s: 580; RV32IFZFH: # %bb.0: 581; RV32IFZFH-NEXT: fcvt.h.s fa5, fa1 582; RV32IFZFH-NEXT: fsgnj.h fa0, fa0, fa5 583; RV32IFZFH-NEXT: ret 584; 585; RV32IFDZFH-LABEL: fold_demote_h_s: 586; RV32IFDZFH: # %bb.0: 587; RV32IFDZFH-NEXT: fcvt.h.s fa5, fa1 588; RV32IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5 589; RV32IFDZFH-NEXT: ret 590; 591; RV64IFDZFH-LABEL: fold_demote_h_s: 592; RV64IFDZFH: # %bb.0: 593; RV64IFDZFH-NEXT: fcvt.h.s fa5, fa1 594; RV64IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5 595; RV64IFDZFH-NEXT: ret 596; 597; RV32IFZFHMIN-LABEL: fold_demote_h_s: 598; RV32IFZFHMIN: # %bb.0: 599; RV32IFZFHMIN-NEXT: fmv.x.w a0, fa1 600; RV32IFZFHMIN-NEXT: fmv.x.h a1, fa0 601; RV32IFZFHMIN-NEXT: srli a0, a0, 31 602; RV32IFZFHMIN-NEXT: slli a1, a1, 17 603; RV32IFZFHMIN-NEXT: slli a0, a0, 15 604; RV32IFZFHMIN-NEXT: srli a1, a1, 17 605; RV32IFZFHMIN-NEXT: or a0, a1, a0 606; RV32IFZFHMIN-NEXT: fmv.h.x fa0, a0 607; RV32IFZFHMIN-NEXT: ret 608; 609; RV32IFDZFHMIN-LABEL: fold_demote_h_s: 610; RV32IFDZFHMIN: # %bb.0: 611; RV32IFDZFHMIN-NEXT: fmv.x.w a0, fa1 612; RV32IFDZFHMIN-NEXT: fmv.x.h a1, fa0 613; RV32IFDZFHMIN-NEXT: srli a0, a0, 31 614; RV32IFDZFHMIN-NEXT: slli a1, a1, 17 615; RV32IFDZFHMIN-NEXT: slli a0, a0, 15 616; RV32IFDZFHMIN-NEXT: srli a1, a1, 17 617; RV32IFDZFHMIN-NEXT: or a0, a1, a0 618; RV32IFDZFHMIN-NEXT: fmv.h.x fa0, a0 619; RV32IFDZFHMIN-NEXT: ret 620; 621; RV64IFDZFHMIN-LABEL: fold_demote_h_s: 622; RV64IFDZFHMIN: # %bb.0: 623; RV64IFDZFHMIN-NEXT: fmv.x.w a0, fa1 624; RV64IFDZFHMIN-NEXT: fmv.x.h a1, fa0 625; RV64IFDZFHMIN-NEXT: srli a0, a0, 31 626; RV64IFDZFHMIN-NEXT: slli a1, a1, 49 627; RV64IFDZFHMIN-NEXT: slli a0, a0, 15 628; RV64IFDZFHMIN-NEXT: srli a1, a1, 49 629; RV64IFDZFHMIN-NEXT: or a0, a1, a0 630; RV64IFDZFHMIN-NEXT: fmv.h.x fa0, a0 631; RV64IFDZFHMIN-NEXT: ret 632; 633; RV32IZDINX-LABEL: fold_demote_h_s: 634; RV32IZDINX: # %bb.0: 635; RV32IZDINX-NEXT: # kill: def $x11_w killed $x11_w def $x11 636; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10 637; RV32IZDINX-NEXT: lui a2, 524288 638; RV32IZDINX-NEXT: slli a0, a0, 17 639; RV32IZDINX-NEXT: and a1, a1, a2 640; RV32IZDINX-NEXT: lui a2, 1048560 641; RV32IZDINX-NEXT: srli a0, a0, 17 642; RV32IZDINX-NEXT: srli a1, a1, 16 643; RV32IZDINX-NEXT: or a0, a0, a2 644; RV32IZDINX-NEXT: or a0, a0, a1 645; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10 646; RV32IZDINX-NEXT: ret 647; 648; RV64IZDINX-LABEL: fold_demote_h_s: 649; RV64IZDINX: # %bb.0: 650; RV64IZDINX-NEXT: # kill: def $x11_w killed $x11_w def $x11 651; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10 652; RV64IZDINX-NEXT: lui a2, 524288 653; RV64IZDINX-NEXT: slli a0, a0, 49 654; RV64IZDINX-NEXT: and a1, a1, a2 655; RV64IZDINX-NEXT: lui a2, 1048560 656; RV64IZDINX-NEXT: srli a0, a0, 49 657; RV64IZDINX-NEXT: srli a1, a1, 16 658; RV64IZDINX-NEXT: or a0, a0, a2 659; RV64IZDINX-NEXT: or a0, a0, a1 660; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10 661; RV64IZDINX-NEXT: ret 662 %c = fptrunc float %b to half 663 %t = call half @llvm.copysign.f16(half %a, half %c) 664 ret half %t 665} 666 667define half @fold_demote_h_d(half %a, double %b) nounwind { 668; RV32I-LABEL: fold_demote_h_d: 669; RV32I: # %bb.0: 670; RV32I-NEXT: lui a1, 524288 671; RV32I-NEXT: slli a0, a0, 17 672; RV32I-NEXT: and a1, a2, a1 673; RV32I-NEXT: srli a1, a1, 16 674; RV32I-NEXT: srli a0, a0, 17 675; RV32I-NEXT: or a0, a0, a1 676; RV32I-NEXT: ret 677; 678; RV64I-LABEL: fold_demote_h_d: 679; RV64I: # %bb.0: 680; RV64I-NEXT: slli a0, a0, 49 681; RV64I-NEXT: srli a1, a1, 63 682; RV64I-NEXT: srli a0, a0, 49 683; RV64I-NEXT: slli a1, a1, 63 684; RV64I-NEXT: srli a1, a1, 48 685; RV64I-NEXT: or a0, a0, a1 686; RV64I-NEXT: ret 687; 688; RV32IF-LABEL: fold_demote_h_d: 689; RV32IF: # %bb.0: 690; RV32IF-NEXT: fmv.x.w a0, fa0 691; RV32IF-NEXT: lui a2, 524288 692; RV32IF-NEXT: and a1, a1, a2 693; RV32IF-NEXT: slli a0, a0, 17 694; RV32IF-NEXT: srli a1, a1, 16 695; RV32IF-NEXT: srli a0, a0, 17 696; RV32IF-NEXT: or a0, a0, a1 697; RV32IF-NEXT: lui a1, 1048560 698; RV32IF-NEXT: or a0, a0, a1 699; RV32IF-NEXT: fmv.w.x fa0, a0 700; RV32IF-NEXT: ret 701; 702; RV32IFD-LABEL: fold_demote_h_d: 703; RV32IFD: # %bb.0: 704; RV32IFD-NEXT: addi sp, sp, -16 705; RV32IFD-NEXT: fsd fa1, 8(sp) 706; RV32IFD-NEXT: lw a0, 12(sp) 707; RV32IFD-NEXT: fmv.x.w a1, fa0 708; RV32IFD-NEXT: lui a2, 524288 709; RV32IFD-NEXT: and a0, a0, a2 710; RV32IFD-NEXT: lui a2, 1048560 711; RV32IFD-NEXT: slli a1, a1, 17 712; RV32IFD-NEXT: srli a1, a1, 17 713; RV32IFD-NEXT: srli a0, a0, 16 714; RV32IFD-NEXT: or a1, a1, a2 715; RV32IFD-NEXT: or a0, a1, a0 716; RV32IFD-NEXT: fmv.w.x fa0, a0 717; RV32IFD-NEXT: addi sp, sp, 16 718; RV32IFD-NEXT: ret 719; 720; RV64IFD-LABEL: fold_demote_h_d: 721; RV64IFD: # %bb.0: 722; RV64IFD-NEXT: fmv.x.d a0, fa1 723; RV64IFD-NEXT: fmv.x.w a1, fa0 724; RV64IFD-NEXT: lui a2, 1048560 725; RV64IFD-NEXT: slli a1, a1, 49 726; RV64IFD-NEXT: srli a0, a0, 63 727; RV64IFD-NEXT: srli a1, a1, 49 728; RV64IFD-NEXT: slli a0, a0, 63 729; RV64IFD-NEXT: srli a0, a0, 48 730; RV64IFD-NEXT: or a1, a1, a2 731; RV64IFD-NEXT: or a0, a1, a0 732; RV64IFD-NEXT: fmv.w.x fa0, a0 733; RV64IFD-NEXT: ret 734; 735; RV32IFZFH-LABEL: fold_demote_h_d: 736; RV32IFZFH: # %bb.0: 737; RV32IFZFH-NEXT: srli a1, a1, 16 738; RV32IFZFH-NEXT: fmv.h.x fa5, a1 739; RV32IFZFH-NEXT: fsgnj.h fa0, fa0, fa5 740; RV32IFZFH-NEXT: ret 741; 742; RV32IFDZFH-LABEL: fold_demote_h_d: 743; RV32IFDZFH: # %bb.0: 744; RV32IFDZFH-NEXT: fcvt.h.d fa5, fa1 745; RV32IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5 746; RV32IFDZFH-NEXT: ret 747; 748; RV64IFDZFH-LABEL: fold_demote_h_d: 749; RV64IFDZFH: # %bb.0: 750; RV64IFDZFH-NEXT: fcvt.h.d fa5, fa1 751; RV64IFDZFH-NEXT: fsgnj.h fa0, fa0, fa5 752; RV64IFDZFH-NEXT: ret 753; 754; RV32IFZFHMIN-LABEL: fold_demote_h_d: 755; RV32IFZFHMIN: # %bb.0: 756; RV32IFZFHMIN-NEXT: srli a1, a1, 31 757; RV32IFZFHMIN-NEXT: fmv.x.h a0, fa0 758; RV32IFZFHMIN-NEXT: slli a1, a1, 15 759; RV32IFZFHMIN-NEXT: slli a0, a0, 17 760; RV32IFZFHMIN-NEXT: srli a0, a0, 17 761; RV32IFZFHMIN-NEXT: or a0, a0, a1 762; RV32IFZFHMIN-NEXT: fmv.h.x fa0, a0 763; RV32IFZFHMIN-NEXT: ret 764; 765; RV32IFDZFHMIN-LABEL: fold_demote_h_d: 766; RV32IFDZFHMIN: # %bb.0: 767; RV32IFDZFHMIN-NEXT: addi sp, sp, -16 768; RV32IFDZFHMIN-NEXT: fsd fa1, 8(sp) 769; RV32IFDZFHMIN-NEXT: lw a0, 12(sp) 770; RV32IFDZFHMIN-NEXT: fmv.x.h a1, fa0 771; RV32IFDZFHMIN-NEXT: slli a1, a1, 17 772; RV32IFDZFHMIN-NEXT: srli a0, a0, 31 773; RV32IFDZFHMIN-NEXT: slli a0, a0, 15 774; RV32IFDZFHMIN-NEXT: srli a1, a1, 17 775; RV32IFDZFHMIN-NEXT: or a0, a1, a0 776; RV32IFDZFHMIN-NEXT: fmv.h.x fa0, a0 777; RV32IFDZFHMIN-NEXT: addi sp, sp, 16 778; RV32IFDZFHMIN-NEXT: ret 779; 780; RV64IFDZFHMIN-LABEL: fold_demote_h_d: 781; RV64IFDZFHMIN: # %bb.0: 782; RV64IFDZFHMIN-NEXT: fmv.x.d a0, fa1 783; RV64IFDZFHMIN-NEXT: fmv.x.h a1, fa0 784; RV64IFDZFHMIN-NEXT: srli a0, a0, 63 785; RV64IFDZFHMIN-NEXT: slli a1, a1, 49 786; RV64IFDZFHMIN-NEXT: slli a0, a0, 15 787; RV64IFDZFHMIN-NEXT: srli a1, a1, 49 788; RV64IFDZFHMIN-NEXT: or a0, a1, a0 789; RV64IFDZFHMIN-NEXT: fmv.h.x fa0, a0 790; RV64IFDZFHMIN-NEXT: ret 791; 792; RV32IZDINX-LABEL: fold_demote_h_d: 793; RV32IZDINX: # %bb.0: 794; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10 795; RV32IZDINX-NEXT: lui a1, 524288 796; RV32IZDINX-NEXT: slli a0, a0, 17 797; RV32IZDINX-NEXT: and a1, a2, a1 798; RV32IZDINX-NEXT: lui a2, 1048560 799; RV32IZDINX-NEXT: srli a0, a0, 17 800; RV32IZDINX-NEXT: srli a1, a1, 16 801; RV32IZDINX-NEXT: or a0, a0, a2 802; RV32IZDINX-NEXT: or a0, a0, a1 803; RV32IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10 804; RV32IZDINX-NEXT: ret 805; 806; RV64IZDINX-LABEL: fold_demote_h_d: 807; RV64IZDINX: # %bb.0: 808; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w def $x10 809; RV64IZDINX-NEXT: slli a0, a0, 49 810; RV64IZDINX-NEXT: srli a1, a1, 63 811; RV64IZDINX-NEXT: lui a2, 1048560 812; RV64IZDINX-NEXT: srli a0, a0, 49 813; RV64IZDINX-NEXT: slli a1, a1, 63 814; RV64IZDINX-NEXT: srli a1, a1, 48 815; RV64IZDINX-NEXT: or a0, a0, a2 816; RV64IZDINX-NEXT: or a0, a0, a1 817; RV64IZDINX-NEXT: # kill: def $x10_w killed $x10_w killed $x10 818; RV64IZDINX-NEXT: ret 819 %c = fptrunc double %b to half 820 %t = call half @llvm.copysign.f16(half %a, half %c) 821 ret half %t 822} 823