conditional operator

Hi!

when using something like
(a < b) ? a : b

I would expect that the select instruction is always used.
But, if a or b are a global variable, a real branch with multiple
basic blocks is created. Is this a bug or a feature?

-Jochen

It's a feature. It is up to the optimizer to form the select. If a or b is volatile (or if they are other expressions with side effects), the transformation is invalid.

-Chris

Hello Jochen-

Your expectation is incorrect, I'm afraid. Typically this would be expanded
to something like this:

   …
   %cmp = …
   br i1 %cmp, label %ternary.true, label %ternary.false
ternary.true:
   %truevalue = …
   br label %ternary.end
ternary.false:
   %falsevalue = …
   br label %ternary.end
ternary.end:
   %value = phi %type [%truevalue, %ternary.true], [%falsevalue, %ternary.false]

This may then be optimised to a select by later passes, if it's considered to be
profitable to do so.

The reason for this is that C requires that only the value which is needed
is evaluated. If one of the selected values has a side effect, this becomes significant.

Alistair

The reason for this is that C requires that only the value which is needed
is evaluated. If one of the selected values has a side effect, this becomes significant.
  

Ah, I see. But in my case I have only normal variables (local or global), no volatile and no functions.
Therefore I wonder why the optimizer misses it in some cases (with globals).

-Jochen

It normally gets optimized... can you attach a testcase?

-Eli

This is by design, generating a select requires analyzing the operands
in the ?: operator to determine whether they have side effects. We
generally prefer to leave those kinds of optimizations to the backend,
unless there is a clear compile time opportunity.

- Daniel

It normally gets optimized... can you attach a testcase?
   

This is my testcase:

float a;
float b;
float x;
extern "C" void main()
{
     x = a > b ? a : b;
}

This are my optimizations:
     llvm::PassManager passManager;
     passManager.add(new llvm::TargetData(targetDescription));
     passManager.add(llvm::createFunctionInliningPass(2000));
     passManager.add(llvm::createScalarReplAggregatesPass(1000000));
     passManager.add(llvm::createInstructionCombiningPass());
     passManager.add(llvm::createDeadInstEliminationPass());
     passManager.add(llvm::createDeadStoreEliminationPass());
     passManager.add(llvm::createDeadTypeEliminationPass());

This my language options
     langOptions.Bool = 1;
     langOptions.CPlusPlus = 1;
     langOptions.RTTI = 0;
     langOptions.AltiVec = 1;
     langOptions.Freestanding = 1;

-Jochen