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?
// -0.0 - X --> G_FNEG
if (isa<Constant>(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<Instruction>(U)) {
+ const Instruction &I = cast<Instruction>(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<Instruction>(U)) {
+ const Instruction &I = cast<Instruction>(U);
+ Flags = MachineInstr::copyFlagsFromInstruction(I);
+ }
+ MIRBuilder.buildInstr(TargetOpcode::G_FNEG, {Res}, {Op0}, Flags);
return true;
}
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
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
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