Add minnum / maxnum codegen
[oota-llvm.git] / lib / Target / R600 / SIInstrInfo.cpp
index eb8d38cd1840f4816f9903bd4756f4c4b78b7303..4de885c23d1cf4d74e4b2299f483ef43aef55381 100644 (file)
@@ -705,7 +705,7 @@ MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
 
   MachineOperand &Src1 = MI->getOperand(Src1Idx);
 
-  // Make sure it s legal to commute operands for VOP2.
+  // Make sure it's legal to commute operands for VOP2.
   if (isVOP2(MI->getOpcode()) &&
       (!isOperandLegal(MI, Src0Idx, &Src1) ||
        !isOperandLegal(MI, Src1Idx, &Src0)))
@@ -718,19 +718,30 @@ MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
       return nullptr;
     }
 
-    // XXX: Commute VOP3 instructions with abs and neg set .
-    const MachineOperand *Src0Mods = getNamedOperand(*MI,
-                                          AMDGPU::OpName::src0_modifiers);
-    const MachineOperand *Src1Mods = getNamedOperand(*MI,
-                                          AMDGPU::OpName::src1_modifiers);
-    const MachineOperand *Src2Mods = getNamedOperand(*MI,
-                                          AMDGPU::OpName::src2_modifiers);
-
-    if ((Src0Mods && Src0Mods->getImm()) ||
-        (Src1Mods && Src1Mods->getImm()) ||
-        (Src2Mods && Src2Mods->getImm()))
+    // TODO: Is there any reason to commute with src2 modifiers?
+    // TODO: Should be able to commute with output modifiers just fine.
+    if (hasModifiersSet(*MI, AMDGPU::OpName::src2_modifiers))
       return nullptr;
 
+    // Be sure to copy the source modifiers to the right place.
+    if (MachineOperand *Src0Mods
+          = getNamedOperand(*MI, AMDGPU::OpName::src0_modifiers)) {
+      MachineOperand *Src1Mods
+        = getNamedOperand(*MI, AMDGPU::OpName::src1_modifiers);
+
+      int Src0ModsVal = Src0Mods->getImm();
+      if (!Src1Mods && Src0ModsVal != 0)
+        return nullptr;
+
+      // XXX - This assert might be a lie. It might be useful to have a neg
+      // modifier with 0.0.
+      int Src1ModsVal = Src1Mods->getImm();
+      assert((Src1ModsVal == 0) && "Not expecting modifiers with immediates");
+
+      Src1Mods->setImm(Src0ModsVal);
+      Src0Mods->setImm(Src1ModsVal);
+    }
+
     unsigned Reg = Src0.getReg();
     unsigned SubReg = Src0.getSubReg();
     if (Src1.isImm())
@@ -779,6 +790,12 @@ bool SIInstrInfo::findCommutedOpIndices(MachineInstr *MI,
   if (!MI->getOperand(Src1Idx).isReg())
     return false;
 
+  // If any source modifiers are set, the generic instruction commuting won't
+  // understand how to copy the source modifiers.
+  if (hasModifiersSet(*MI, AMDGPU::OpName::src0_modifiers) ||
+      hasModifiersSet(*MI, AMDGPU::OpName::src1_modifiers))
+    return false;
+
   SrcOpIdx1 = Src0Idx;
   SrcOpIdx2 = Src1Idx;
   return true;
@@ -982,6 +999,12 @@ bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
                                     AMDGPU::OpName::src0_modifiers) != -1;
 }
 
+bool SIInstrInfo::hasModifiersSet(const MachineInstr &MI,
+                                  unsigned OpName) const {
+  const MachineOperand *Mods = getNamedOperand(MI, OpName);
+  return Mods && Mods->getImm();
+}
+
 bool SIInstrInfo::usesConstantBus(const MachineRegisterInfo &MRI,
                                   const MachineOperand &MO) const {
   // Literal constants use the constant bus.
@@ -2300,7 +2323,7 @@ void SIInstrInfo::reserveIndirectRegisters(BitVector &Reserved,
 }
 
 MachineOperand *SIInstrInfo::getNamedOperand(MachineInstr &MI,
-                                                   unsigned OperandName) const {
+                                             unsigned OperandName) const {
   int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
   if (Idx == -1)
     return nullptr;