1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32F %s 4; RUN: llc -mtriple=riscv32 -mattr=+f,+d -verify-machineinstrs < %s \ 5; RUN: | FileCheck -check-prefix=RV32FD %s 6; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ 7; RUN: | FileCheck -check-prefix=RV64F %s 8; RUN: llc -mtriple=riscv64 -mattr=+f,+d -verify-machineinstrs < %s \ 9; RUN: | FileCheck -check-prefix=RV64FD %s 10 11; These functions perform extra work to ensure that `%a3` starts in a 12; floating-point register, if the machine has them, and the result of 13; the bitwise operation is then needed in a floating-point register. 14; This should mean the optimisations will fire even if you're using the 15; soft-float ABI on a machine with hardware floating-point support. 16 17define float @bitcast_and(float %a1, float %a2) nounwind { 18; RV32F-LABEL: bitcast_and: 19; RV32F: # %bb.0: 20; RV32F-NEXT: fmv.w.x ft0, a1 21; RV32F-NEXT: fmv.w.x ft1, a0 22; RV32F-NEXT: fadd.s ft0, ft1, ft0 23; RV32F-NEXT: fabs.s ft0, ft0 24; RV32F-NEXT: fadd.s ft0, ft1, ft0 25; RV32F-NEXT: fmv.x.w a0, ft0 26; RV32F-NEXT: ret 27; 28; RV32FD-LABEL: bitcast_and: 29; RV32FD: # %bb.0: 30; RV32FD-NEXT: fmv.w.x ft0, a1 31; RV32FD-NEXT: fmv.w.x ft1, a0 32; RV32FD-NEXT: fadd.s ft0, ft1, ft0 33; RV32FD-NEXT: fabs.s ft0, ft0 34; RV32FD-NEXT: fadd.s ft0, ft1, ft0 35; RV32FD-NEXT: fmv.x.w a0, ft0 36; RV32FD-NEXT: ret 37; 38; RV64F-LABEL: bitcast_and: 39; RV64F: # %bb.0: 40; RV64F-NEXT: fmv.w.x ft0, a1 41; RV64F-NEXT: fmv.w.x ft1, a0 42; RV64F-NEXT: fadd.s ft0, ft1, ft0 43; RV64F-NEXT: fabs.s ft0, ft0 44; RV64F-NEXT: fadd.s ft0, ft1, ft0 45; RV64F-NEXT: fmv.x.w a0, ft0 46; RV64F-NEXT: ret 47; 48; RV64FD-LABEL: bitcast_and: 49; RV64FD: # %bb.0: 50; RV64FD-NEXT: fmv.w.x ft0, a1 51; RV64FD-NEXT: fmv.w.x ft1, a0 52; RV64FD-NEXT: fadd.s ft0, ft1, ft0 53; RV64FD-NEXT: fabs.s ft0, ft0 54; RV64FD-NEXT: fadd.s ft0, ft1, ft0 55; RV64FD-NEXT: fmv.x.w a0, ft0 56; RV64FD-NEXT: ret 57 %a3 = fadd float %a1, %a2 58 %bc1 = bitcast float %a3 to i32 59 %and = and i32 %bc1, 2147483647 60 %bc2 = bitcast i32 %and to float 61 %a4 = fadd float %a1, %bc2 62 ret float %a4 63} 64 65define double @bitcast_double_and(double %a1, double %a2) nounwind { 66; RV32F-LABEL: bitcast_double_and: 67; RV32F: # %bb.0: 68; RV32F-NEXT: addi sp, sp, -16 69; RV32F-NEXT: sw ra, 12(sp) 70; RV32F-NEXT: sw s0, 8(sp) 71; RV32F-NEXT: sw s1, 4(sp) 72; RV32F-NEXT: mv s0, a1 73; RV32F-NEXT: mv s1, a0 74; RV32F-NEXT: call __adddf3 75; RV32F-NEXT: mv a2, a0 76; RV32F-NEXT: lui a0, 524288 77; RV32F-NEXT: addi a0, a0, -1 78; RV32F-NEXT: and a3, a1, a0 79; RV32F-NEXT: mv a0, s1 80; RV32F-NEXT: mv a1, s0 81; RV32F-NEXT: call __adddf3 82; RV32F-NEXT: lw s1, 4(sp) 83; RV32F-NEXT: lw s0, 8(sp) 84; RV32F-NEXT: lw ra, 12(sp) 85; RV32F-NEXT: addi sp, sp, 16 86; RV32F-NEXT: ret 87; 88; RV32FD-LABEL: bitcast_double_and: 89; RV32FD: # %bb.0: 90; RV32FD-NEXT: addi sp, sp, -16 91; RV32FD-NEXT: sw a2, 8(sp) 92; RV32FD-NEXT: sw a3, 12(sp) 93; RV32FD-NEXT: fld ft0, 8(sp) 94; RV32FD-NEXT: sw a0, 8(sp) 95; RV32FD-NEXT: sw a1, 12(sp) 96; RV32FD-NEXT: fld ft1, 8(sp) 97; RV32FD-NEXT: fadd.d ft0, ft1, ft0 98; RV32FD-NEXT: fabs.d ft0, ft0 99; RV32FD-NEXT: fadd.d ft0, ft1, ft0 100; RV32FD-NEXT: fsd ft0, 8(sp) 101; RV32FD-NEXT: lw a0, 8(sp) 102; RV32FD-NEXT: lw a1, 12(sp) 103; RV32FD-NEXT: addi sp, sp, 16 104; RV32FD-NEXT: ret 105; 106; RV64F-LABEL: bitcast_double_and: 107; RV64F: # %bb.0: 108; RV64F-NEXT: addi sp, sp, -16 109; RV64F-NEXT: sd ra, 8(sp) 110; RV64F-NEXT: sd s0, 0(sp) 111; RV64F-NEXT: mv s0, a0 112; RV64F-NEXT: call __adddf3 113; RV64F-NEXT: addi a1, zero, -1 114; RV64F-NEXT: slli a1, a1, 63 115; RV64F-NEXT: addi a1, a1, -1 116; RV64F-NEXT: and a1, a0, a1 117; RV64F-NEXT: mv a0, s0 118; RV64F-NEXT: call __adddf3 119; RV64F-NEXT: ld s0, 0(sp) 120; RV64F-NEXT: ld ra, 8(sp) 121; RV64F-NEXT: addi sp, sp, 16 122; RV64F-NEXT: ret 123; 124; RV64FD-LABEL: bitcast_double_and: 125; RV64FD: # %bb.0: 126; RV64FD-NEXT: fmv.d.x ft0, a1 127; RV64FD-NEXT: fmv.d.x ft1, a0 128; RV64FD-NEXT: fadd.d ft0, ft1, ft0 129; RV64FD-NEXT: fabs.d ft0, ft0 130; RV64FD-NEXT: fadd.d ft0, ft1, ft0 131; RV64FD-NEXT: fmv.x.d a0, ft0 132; RV64FD-NEXT: ret 133 %a3 = fadd double %a1, %a2 134 %bc1 = bitcast double %a3 to i64 135 %and = and i64 %bc1, 9223372036854775807 136 %bc2 = bitcast i64 %and to double 137 %a4 = fadd double %a1, %bc2 138 ret double %a4 139} 140 141 142define float @bitcast_xor(float %a1, float %a2) nounwind { 143; RV32F-LABEL: bitcast_xor: 144; RV32F: # %bb.0: 145; RV32F-NEXT: fmv.w.x ft0, a1 146; RV32F-NEXT: fmv.w.x ft1, a0 147; RV32F-NEXT: fmul.s ft0, ft1, ft0 148; RV32F-NEXT: fneg.s ft0, ft0 149; RV32F-NEXT: fmul.s ft0, ft1, ft0 150; RV32F-NEXT: fmv.x.w a0, ft0 151; RV32F-NEXT: ret 152; 153; RV32FD-LABEL: bitcast_xor: 154; RV32FD: # %bb.0: 155; RV32FD-NEXT: fmv.w.x ft0, a1 156; RV32FD-NEXT: fmv.w.x ft1, a0 157; RV32FD-NEXT: fmul.s ft0, ft1, ft0 158; RV32FD-NEXT: fneg.s ft0, ft0 159; RV32FD-NEXT: fmul.s ft0, ft1, ft0 160; RV32FD-NEXT: fmv.x.w a0, ft0 161; RV32FD-NEXT: ret 162; 163; RV64F-LABEL: bitcast_xor: 164; RV64F: # %bb.0: 165; RV64F-NEXT: fmv.w.x ft0, a1 166; RV64F-NEXT: fmv.w.x ft1, a0 167; RV64F-NEXT: fmul.s ft0, ft1, ft0 168; RV64F-NEXT: fneg.s ft0, ft0 169; RV64F-NEXT: fmul.s ft0, ft1, ft0 170; RV64F-NEXT: fmv.x.w a0, ft0 171; RV64F-NEXT: ret 172; 173; RV64FD-LABEL: bitcast_xor: 174; RV64FD: # %bb.0: 175; RV64FD-NEXT: fmv.w.x ft0, a1 176; RV64FD-NEXT: fmv.w.x ft1, a0 177; RV64FD-NEXT: fmul.s ft0, ft1, ft0 178; RV64FD-NEXT: fneg.s ft0, ft0 179; RV64FD-NEXT: fmul.s ft0, ft1, ft0 180; RV64FD-NEXT: fmv.x.w a0, ft0 181; RV64FD-NEXT: ret 182 %a3 = fmul float %a1, %a2 183 %bc1 = bitcast float %a3 to i32 184 %and = xor i32 %bc1, 2147483648 185 %bc2 = bitcast i32 %and to float 186 %a4 = fmul float %a1, %bc2 187 ret float %a4 188} 189 190define double @bitcast_double_xor(double %a1, double %a2) nounwind { 191; RV32F-LABEL: bitcast_double_xor: 192; RV32F: # %bb.0: 193; RV32F-NEXT: addi sp, sp, -16 194; RV32F-NEXT: sw ra, 12(sp) 195; RV32F-NEXT: sw s0, 8(sp) 196; RV32F-NEXT: sw s1, 4(sp) 197; RV32F-NEXT: mv s0, a1 198; RV32F-NEXT: mv s1, a0 199; RV32F-NEXT: call __muldf3 200; RV32F-NEXT: mv a2, a0 201; RV32F-NEXT: lui a0, 524288 202; RV32F-NEXT: xor a3, a1, a0 203; RV32F-NEXT: mv a0, s1 204; RV32F-NEXT: mv a1, s0 205; RV32F-NEXT: call __muldf3 206; RV32F-NEXT: lw s1, 4(sp) 207; RV32F-NEXT: lw s0, 8(sp) 208; RV32F-NEXT: lw ra, 12(sp) 209; RV32F-NEXT: addi sp, sp, 16 210; RV32F-NEXT: ret 211; 212; RV32FD-LABEL: bitcast_double_xor: 213; RV32FD: # %bb.0: 214; RV32FD-NEXT: addi sp, sp, -16 215; RV32FD-NEXT: sw a2, 8(sp) 216; RV32FD-NEXT: sw a3, 12(sp) 217; RV32FD-NEXT: fld ft0, 8(sp) 218; RV32FD-NEXT: sw a0, 8(sp) 219; RV32FD-NEXT: sw a1, 12(sp) 220; RV32FD-NEXT: fld ft1, 8(sp) 221; RV32FD-NEXT: fmul.d ft0, ft1, ft0 222; RV32FD-NEXT: fneg.d ft0, ft0 223; RV32FD-NEXT: fmul.d ft0, ft1, ft0 224; RV32FD-NEXT: fsd ft0, 8(sp) 225; RV32FD-NEXT: lw a0, 8(sp) 226; RV32FD-NEXT: lw a1, 12(sp) 227; RV32FD-NEXT: addi sp, sp, 16 228; RV32FD-NEXT: ret 229; 230; RV64F-LABEL: bitcast_double_xor: 231; RV64F: # %bb.0: 232; RV64F-NEXT: addi sp, sp, -16 233; RV64F-NEXT: sd ra, 8(sp) 234; RV64F-NEXT: sd s0, 0(sp) 235; RV64F-NEXT: mv s0, a0 236; RV64F-NEXT: call __muldf3 237; RV64F-NEXT: addi a1, zero, -1 238; RV64F-NEXT: slli a1, a1, 63 239; RV64F-NEXT: xor a1, a0, a1 240; RV64F-NEXT: mv a0, s0 241; RV64F-NEXT: call __muldf3 242; RV64F-NEXT: ld s0, 0(sp) 243; RV64F-NEXT: ld ra, 8(sp) 244; RV64F-NEXT: addi sp, sp, 16 245; RV64F-NEXT: ret 246; 247; RV64FD-LABEL: bitcast_double_xor: 248; RV64FD: # %bb.0: 249; RV64FD-NEXT: fmv.d.x ft0, a1 250; RV64FD-NEXT: fmv.d.x ft1, a0 251; RV64FD-NEXT: fmul.d ft0, ft1, ft0 252; RV64FD-NEXT: fneg.d ft0, ft0 253; RV64FD-NEXT: fmul.d ft0, ft1, ft0 254; RV64FD-NEXT: fmv.x.d a0, ft0 255; RV64FD-NEXT: ret 256 %a3 = fmul double %a1, %a2 257 %bc1 = bitcast double %a3 to i64 258 %and = xor i64 %bc1, 9223372036854775808 259 %bc2 = bitcast i64 %and to double 260 %a4 = fmul double %a1, %bc2 261 ret double %a4 262} 263 264define float @bitcast_or(float %a1, float %a2) nounwind { 265; RV32F-LABEL: bitcast_or: 266; RV32F: # %bb.0: 267; RV32F-NEXT: fmv.w.x ft0, a1 268; RV32F-NEXT: fmv.w.x ft1, a0 269; RV32F-NEXT: fmul.s ft0, ft1, ft0 270; RV32F-NEXT: fabs.s ft0, ft0 271; RV32F-NEXT: fneg.s ft0, ft0 272; RV32F-NEXT: fmul.s ft0, ft1, ft0 273; RV32F-NEXT: fmv.x.w a0, ft0 274; RV32F-NEXT: ret 275; 276; RV32FD-LABEL: bitcast_or: 277; RV32FD: # %bb.0: 278; RV32FD-NEXT: fmv.w.x ft0, a1 279; RV32FD-NEXT: fmv.w.x ft1, a0 280; RV32FD-NEXT: fmul.s ft0, ft1, ft0 281; RV32FD-NEXT: fabs.s ft0, ft0 282; RV32FD-NEXT: fneg.s ft0, ft0 283; RV32FD-NEXT: fmul.s ft0, ft1, ft0 284; RV32FD-NEXT: fmv.x.w a0, ft0 285; RV32FD-NEXT: ret 286; 287; RV64F-LABEL: bitcast_or: 288; RV64F: # %bb.0: 289; RV64F-NEXT: fmv.w.x ft0, a1 290; RV64F-NEXT: fmv.w.x ft1, a0 291; RV64F-NEXT: fmul.s ft0, ft1, ft0 292; RV64F-NEXT: fabs.s ft0, ft0 293; RV64F-NEXT: fneg.s ft0, ft0 294; RV64F-NEXT: fmul.s ft0, ft1, ft0 295; RV64F-NEXT: fmv.x.w a0, ft0 296; RV64F-NEXT: ret 297; 298; RV64FD-LABEL: bitcast_or: 299; RV64FD: # %bb.0: 300; RV64FD-NEXT: fmv.w.x ft0, a1 301; RV64FD-NEXT: fmv.w.x ft1, a0 302; RV64FD-NEXT: fmul.s ft0, ft1, ft0 303; RV64FD-NEXT: fabs.s ft0, ft0 304; RV64FD-NEXT: fneg.s ft0, ft0 305; RV64FD-NEXT: fmul.s ft0, ft1, ft0 306; RV64FD-NEXT: fmv.x.w a0, ft0 307; RV64FD-NEXT: ret 308 %a3 = fmul float %a1, %a2 309 %bc1 = bitcast float %a3 to i32 310 %and = or i32 %bc1, 2147483648 311 %bc2 = bitcast i32 %and to float 312 %a4 = fmul float %a1, %bc2 313 ret float %a4 314} 315 316define double @bitcast_double_or(double %a1, double %a2) nounwind { 317; RV32F-LABEL: bitcast_double_or: 318; RV32F: # %bb.0: 319; RV32F-NEXT: addi sp, sp, -16 320; RV32F-NEXT: sw ra, 12(sp) 321; RV32F-NEXT: sw s0, 8(sp) 322; RV32F-NEXT: sw s1, 4(sp) 323; RV32F-NEXT: mv s0, a1 324; RV32F-NEXT: mv s1, a0 325; RV32F-NEXT: call __muldf3 326; RV32F-NEXT: mv a2, a0 327; RV32F-NEXT: lui a0, 524288 328; RV32F-NEXT: or a3, a1, a0 329; RV32F-NEXT: mv a0, s1 330; RV32F-NEXT: mv a1, s0 331; RV32F-NEXT: call __muldf3 332; RV32F-NEXT: lw s1, 4(sp) 333; RV32F-NEXT: lw s0, 8(sp) 334; RV32F-NEXT: lw ra, 12(sp) 335; RV32F-NEXT: addi sp, sp, 16 336; RV32F-NEXT: ret 337; 338; RV32FD-LABEL: bitcast_double_or: 339; RV32FD: # %bb.0: 340; RV32FD-NEXT: addi sp, sp, -16 341; RV32FD-NEXT: sw a2, 8(sp) 342; RV32FD-NEXT: sw a3, 12(sp) 343; RV32FD-NEXT: fld ft0, 8(sp) 344; RV32FD-NEXT: sw a0, 8(sp) 345; RV32FD-NEXT: sw a1, 12(sp) 346; RV32FD-NEXT: fld ft1, 8(sp) 347; RV32FD-NEXT: fmul.d ft0, ft1, ft0 348; RV32FD-NEXT: fabs.d ft0, ft0 349; RV32FD-NEXT: fneg.d ft0, ft0 350; RV32FD-NEXT: fmul.d ft0, ft1, ft0 351; RV32FD-NEXT: fsd ft0, 8(sp) 352; RV32FD-NEXT: lw a0, 8(sp) 353; RV32FD-NEXT: lw a1, 12(sp) 354; RV32FD-NEXT: addi sp, sp, 16 355; RV32FD-NEXT: ret 356; 357; RV64F-LABEL: bitcast_double_or: 358; RV64F: # %bb.0: 359; RV64F-NEXT: addi sp, sp, -16 360; RV64F-NEXT: sd ra, 8(sp) 361; RV64F-NEXT: sd s0, 0(sp) 362; RV64F-NEXT: mv s0, a0 363; RV64F-NEXT: call __muldf3 364; RV64F-NEXT: addi a1, zero, -1 365; RV64F-NEXT: slli a1, a1, 63 366; RV64F-NEXT: or a1, a0, a1 367; RV64F-NEXT: mv a0, s0 368; RV64F-NEXT: call __muldf3 369; RV64F-NEXT: ld s0, 0(sp) 370; RV64F-NEXT: ld ra, 8(sp) 371; RV64F-NEXT: addi sp, sp, 16 372; RV64F-NEXT: ret 373; 374; RV64FD-LABEL: bitcast_double_or: 375; RV64FD: # %bb.0: 376; RV64FD-NEXT: fmv.d.x ft0, a1 377; RV64FD-NEXT: fmv.d.x ft1, a0 378; RV64FD-NEXT: fmul.d ft0, ft1, ft0 379; RV64FD-NEXT: fabs.d ft0, ft0 380; RV64FD-NEXT: fneg.d ft0, ft0 381; RV64FD-NEXT: fmul.d ft0, ft1, ft0 382; RV64FD-NEXT: fmv.x.d a0, ft0 383; RV64FD-NEXT: ret 384 %a3 = fmul double %a1, %a2 385 %bc1 = bitcast double %a3 to i64 386 %and = or i64 %bc1, 9223372036854775808 387 %bc2 = bitcast i64 %and to double 388 %a4 = fmul double %a1, %bc2 389 ret double %a4 390} 391