[llvm-dev] Help understanding and lowering LLVM IDS conditional codes correctly

vivek pandya via llvm-dev llvm-dev at lists.llvm.org
Tue Mar 14 11:16:57 PDT 2017


On Tue, Mar 14, 2017 at 9:59 PM, vivek pandya <vivekvpandya at gmail.com>
wrote:

>
>
> On Tue, Mar 14, 2017 at 7:19 PM, Hal Finkel <hfinkel at anl.gov> wrote:
>
>>
>> On 03/14/2017 07:16 AM, vivek pandya wrote:
>>
>> Hello Hal,
>> setCondCodeAction(expand) for un ordered comparison generates
>> semantically wrong code for me for example SETUNE gets converted to SETOE
>> that causes infinite loops.
>>
>>
>> Can you please explain what is happening? It sounds like a bug we should
>> fix.
>>
>> I don't think it is LLVM bug but I am missing some thing or I have not
> implemented something related properly.
> But I will experiment it with and let you my findings.
>
>>
>> What is ideal place where I can convert unordered comparison to un
>> comparison + OR + ordered comparison ?
>> Can I do it by adding required SDNodes ?
>> for example I am trying to do it in LowerBR_CC as shown below:
>>       getFPCCtoMBCC(CC,TCC);
>>       TargetCC = DAG.getConstant(TCC, dl, MVT::i8);
>>       Flag = DAG.getNode(XXXISD::FCMP, dl, MVT::Glue, LHS, RHS,
>>                          TargetCC);
>>       if (isUnordered) {
>>       TCC = XXX::COND_UN;
>>       TargetCC = DAG.getConstant(TCC, dl, MVT::i8);
>>       SDValue UnComp = DAG.getNode(XXX::FCMP, dl, MVT::Glue, LHS, RHS,
>>                                    TargetCC);
>>       Flag = DAG.getNode(ISD::OR, dl, MVT::Glue, Flag, UnComp);
>>       }
>> but here I can't OR 2 MVT::Glue value.
>> How can I compare results of two fcmp SDValue objs?
>>
>>
>> If your FCMP node sets some register, you'd need to read it
>> (DAG.getCopyFromReg).
>>
> Hey Hal,
I have few questions here,
Do you here mean FCMP sets any physical register ? Because as per my
understanding getCopyFromReg() requires a reg operand to copy from.
What if it set some virtual register? Then how to use getCopyFromReg()
method?

getCopyFromReg() requires a Chain operand so I have to make FCMP both Chain
and Glue (by using SDVTList
<http://llvm.org/docs/doxygen/html/structllvm_1_1SDVTList.html> VTs =
getVTList
<http://llvm.org/docs/doxygen/html/classllvm_1_1SelectionDAG.html#a196c23d6cb4d768d037970f1f35bbf66>
(MVT::Other
<http://llvm.org/docs/doxygen/html/classllvm_1_1MVT.html#afd69b4f2dff97a2d7c0192cc769ef50ca62a222acce6360abd2726719fabc2797>,
MVT::Glue
<http://llvm.org/docs/doxygen/html/classllvm_1_1MVT.html#afd69b4f2dff97a2d7c0192cc769ef50ca59a1908cf136662bcfdc11ed49515ca9>
)) right ?

Sincerely,
Vivek

> Ok I will see some examples for getCopyFromReg().
>
> Thanks,
> Vivek
>
>>
>>
>>  -Hal
>>
>>
>>
>> Please provide some guidance.
>>
>> Sincerely,
>> Vivek
>>
>> On Thu, Mar 9, 2017 at 10:29 PM, vivek pandya <vivekvpandya at gmail.com>
>> wrote:
>>
>>>
>>>
>>> On Thu, Mar 9, 2017 at 9:35 PM, Hal Finkel <hfinkel at anl.gov> wrote:
>>>
>>>>
>>>> On 02/25/2017 03:06 AM, vivek pandya via llvm-dev wrote:
>>>>
>>>> Note: Question is written after describing what I have coded.
>>>>
>>>> Hello LLVMDevs,
>>>>
>>>> I am trying to impliment floating point comparsion for an architecture
>>>> which
>>>> supports following type of floating point comparision if FPU is
>>>> available:
>>>> fcmp.un --> true if one of the operand is NaN
>>>> fcmp.lt --> ordered less than, if any input NaN then return false
>>>> fcmp.eq --> ordered equal, if any input NaN then return false
>>>> fcmp.le --> ordered less equal, if any input NaN then return false
>>>> fcmp.gt --> ordered grater than, if any input NaN then return false
>>>> fcmp.ne --> ordered not equal, if any input NaN then return true
>>>> fcmp.ge --> ordered grater equal, if any input NaN then return false
>>>>
>>>> When FPU is not present I need to generate a library call,
>>>>
>>>> so I have added following code in LowerBR_CC function in
>>>> XXXISelLowering.cpp
>>>>
>>>> const XXXSubtarget &STI = static_cast<const XXXSubtarget&>
>>>>                                              (DAG.getSubtarget());
>>>>  XXXCC::CondCodes TCC;
>>>>  getFPCCtoXXCC(CC,TCC);
>>>>  TargetCC = DAG.getConstant(TCC, dl, MVT::i8);
>>>>  if (STI.useHardFloat()) {
>>>>     // if fcmp instruction is available use it
>>>>    SDValue Flag = DAG.getNode(XXXISD::FCMP, dl, MVT::Glue, LHS, RHS,
>>>>                       TargetCC);
>>>>    return DAG.getNode(XXXISD::BR_CC, dl, Op.getValueType(),
>>>>                   Chain, Dest, TargetCC, Flag);
>>>>  }
>>>>  else {
>>>>     // else generate library call
>>>>    DAG.getTargetLoweringInfo().softenSetCCOperands(DAG, MVT::f32, LHS,
>>>> RHS,
>>>>                                                    CC, dl);
>>>>
>>>>    SDValue Flag = DAG.getNode(XXXISD::CMP, dl, MVT::Glue, LHS, RHS);
>>>>
>>>>    if (!RHS.getNode()) {
>>>>      RHS = DAG.getConstant(0, dl, LHS.getValueType());
>>>>      TargetCC = DAG.getConstant(XXXCC::COND_NE, dl, MVT::i8);
>>>>    }
>>>>    return DAG.getNode(XXXISD::BR_CC, dl, MVT::Other,
>>>>                   Chain, Dest, TargetCC, Flag);
>>>>  }
>>>>
>>>>  and code for getFPCCtoXXCC() is as following:
>>>>
>>>>  static void getFPCCtoXXCC(ISD::CondCode CC, XXXCC::CondCodes
>>>> &CondCode) {
>>>>   switch (CC) {
>>>>     default:
>>>>       llvm_unreachable("Unknown FP condition!");
>>>>     case ISD::SETEQ:
>>>>     case ISD::SETOEQ:
>>>>       CondCode = XXXCC::COND_E;
>>>>       break;
>>>>     case ISD::SETGT:
>>>>     case ISD::SETOGT:
>>>>       CondCode = XXXCC::COND_GT;
>>>>       break;
>>>>     case ISD::SETGE:
>>>>     case ISD::SETOGE:
>>>>       CondCode = XXXCC::COND_GE;
>>>>       break;
>>>>     case ISD::SETOLT:
>>>>     case ISD::SETLT:
>>>>       CondCode = XXXCC::COND_LT;
>>>>       break;
>>>>     case ISD::SETOLE:
>>>>     case ISD::SETLE:
>>>>       CondCode = XXXCC::COND_LE;
>>>>       break;
>>>>     case ISD::SETONE:
>>>>     case ISD::SETNE:
>>>>       CondCode = XXXCC::COND_NE;
>>>>       break;
>>>>     case ISD::SETUO:
>>>>       CondCode = XXXCC::COND_UN;
>>>>       break;
>>>>     case ISD::SETO:
>>>>     case ISD::SETUEQ:
>>>>     case ISD::SETUGT:
>>>>     case ISD::SETUGE:
>>>>     case ISD::SETULT:
>>>>     case ISD::SETULE:
>>>>     case ISD::SETUNE:
>>>>       CC = getSetCCInverse(CC,false);
>>>>       getFPCCtoMBCC(CC,CondCode);
>>>>       break;
>>>>   }
>>>> }
>>>>
>>>>  I am generating wrong code when using floating point library call for
>>>> comparions. For the following simple case:
>>>> float branchTest(float a, float b) {
>>>> float retVal;
>>>> if (a == b) {
>>>> retVal = a / b + 22.34;
>>>> }
>>>> return retVal;
>>>> }
>>>> I am getting:
>>>> brlid r15,__nesf2
>>>> nop
>>>> beqi r3,.LBB0_2 ; r3 is return regsiter
>>>>
>>>> Now I want to understand difference between three different version of
>>>> Condition
>>>> Codes for same operation and how according to my target I should handle
>>>> them.
>>>> For example let's consider SETNE, SETONE and SETUNE so for my
>>>> architecture
>>>> I think for floating point all three are same
>>>>
>>>>
>>>> No, they're not the same. Please see:
>>>>
>>>>   http://llvm.org/docs/LangRef.html#id290
>>>>
>>>> which explains the difference between SETONE (one) and SETUNE (une).
>>>> Regarding how SETNE is interpreted for FP, see the comment in the
>>>> definition of CondCode in include/llvm/CodeGen/ISDOpcodes.h which
>>>> explains, "// Don't care operations: undefined if the input is a nan.".
>>>>
>>>> To support the unordered comparisons, if your FPU has only ordered
>>>> comparisons, then you might need to do the underlying comparison, and a NaN
>>>> check, and then OR the results. I think that using setCondCodeAction will
>>>> cause the expansions for the hardware-unsupported variants to happen for
>>>> you.
>>>>
>>>>  -Hal
>>>>
>>>
>>> Thanks Hal for the guidance !
>>>
>>> -Vivek
>>>
>>>>
>>>> so do I need to use
>>>> getSetCCInverse() ? Also when I look at the code of
>>>> TargetLowering::softenSetCCOperands I see that for some condition code
>>>> it uses
>>>> getSetCCInverse() and also I am not able to understand the way it
>>>> groups
>>>> condition code in switch case for example :
>>>>   case ISD::SETEQ:
>>>>   case ISD::SETOEQ:
>>>>     LC1 = (VT == MVT::f32) ? RTLIB::OEQ_F32 :
>>>>           (VT == MVT::f64) ? RTLIB::OEQ_F64 : RTLIB::OEQ_F128;
>>>>     break;
>>>>   case ISD::SETNE:
>>>>   case ISD::SETUNE:
>>>>     LC1 = (VT == MVT::f32) ? RTLIB::UNE_F32 :
>>>>           (VT == MVT::f64) ? RTLIB::UNE_F64 : RTLIB::UNE_F128;
>>>>     break;
>>>> here why SETNE and SETUNE is considered same, why SETONE is considered
>>>> differently. Is there any guideline to lower conditional code properly?
>>>>
>>>> Sincerely,
>>>> Vivek
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> LLVM Developers mailing listllvm-dev at lists.llvm.orghttp://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>>
>>>> --
>>>> Hal Finkel
>>>> Lead, Compiler Technology and Programming Languages
>>>> Leadership Computing Facility
>>>> Argonne National Laboratory
>>>>
>>>> --
>> Hal Finkel
>> Lead, Compiler Technology and Programming Languages
>> Leadership Computing Facility
>> Argonne National Laboratory
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170314/e303dfd9/attachment-0001.html>


More information about the llvm-dev mailing list