Index: llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -285,8 +285,6 @@ bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U, MachineIRBuilder &MIRBuilder) { - // FIXME: handle signed/unsigned wrapping flags. - // Get or create a virtual register for each value. // Unless the value is a Constant => loadimm cst? // or inline constant each time? @@ -308,18 +306,29 @@ // -0.0 - X --> G_FNEG if (isa(U.getOperand(0)) && U.getOperand(0) == ConstantFP::getZeroValueForNegation(U.getType())) { - MIRBuilder.buildInstr(TargetOpcode::G_FNEG) - .addDef(getOrCreateVReg(U)) - .addUse(getOrCreateVReg(*U.getOperand(1))); + unsigned Op1 = getOrCreateVReg(*U.getOperand(1)); + unsigned Res = getOrCreateVReg(U); + uint16_t Flags = 0; + if (isa(U)) { + const Instruction &I = cast(U); + Flags = MachineInstr::copyFlagsFromInstruction(I); + } + // Negate the last operand of the FSUB + MIRBuilder.buildInstr(TargetOpcode::G_FNEG, {Res}, {Op1}, Flags); return true; } return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder); } bool IRTranslator::translateFNeg(const User &U, MachineIRBuilder &MIRBuilder) { - MIRBuilder.buildInstr(TargetOpcode::G_FNEG) - .addDef(getOrCreateVReg(U)) - .addUse(getOrCreateVReg(*U.getOperand(0))); + unsigned Op0 = getOrCreateVReg(*U.getOperand(0)); + unsigned Res = getOrCreateVReg(U); + uint16_t Flags = 0; + if (isa(U)) { + const Instruction &I = cast(U); + Flags = MachineInstr::copyFlagsFromInstruction(I); + } + MIRBuilder.buildInstr(TargetOpcode::G_FNEG, {Res}, {Op0}, Flags); return true; } Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -834,6 +834,16 @@ ret float %res } +; CHECK-LABEL: name: test_fneg_fmf +; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $s0 +; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FNEG [[ARG1]] +; CHECK-NEXT: $s0 = COPY [[RES]] +; CHECK-NEXT: RET_ReallyLR implicit $s0 +define float @test_fneg_fmf(float %arg1) { + %res = fneg fast float %arg1 + ret float %res +} + ; CHECK-LABEL: name: test_sadd_overflow ; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1 @@ -1536,6 +1546,15 @@ ret float %neg } +define float @test_fneg_f32_fmf(float %x) { +; CHECK-LABEL: name: test_fneg_f32 +; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $s0 +; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FNEG [[ARG]] +; CHECK: $s0 = COPY [[RES]](s32) + %neg = fsub fast float -0.000000e+00, %x + ret float %neg +} + define double @test_fneg_f64(double %x) { ; CHECK-LABEL: name: test_fneg_f64 ; CHECK: [[ARG:%[0-9]+]]:_(s64) = COPY $d0 @@ -1545,6 +1564,15 @@ ret double %neg } +define double @test_fneg_f64_fmf(double %x) { +; CHECK-LABEL: name: test_fneg_f64 +; CHECK: [[ARG:%[0-9]+]]:_(s64) = COPY $d0 +; CHECK: [[RES:%[0-9]+]]:_(s64) = nnan ninf nsz arcp contract afn reassoc G_FNEG [[ARG]] +; CHECK: $d0 = COPY [[RES]](s64) + %neg = fsub fast double -0.000000e+00, %x + ret double %neg +} + define void @test_trivial_inlineasm() { ; CHECK-LABEL: name: test_trivial_inlineasm ; CHECK: INLINEASM &wibble, 1