[HN Gopher] The Life of an Optimization Barrier
       ___________________________________________________________________
        
       The Life of an Optimization Barrier
        
       Author : ingve
       Score  : 41 points
       Date   : 2022-01-26 12:20 UTC (1 days ago)
        
 (HTM) web link (blog.trailofbits.com)
 (TXT) w3m dump (blog.trailofbits.com)
        
       | staticassertion wrote:
       | > What is missing is a way forward for getting secret types and
       | the corresponding semantics into LLVM.
       | 
       | Seems crazy that this hasn't happened already given how prevalent
       | and old this issue is.
        
         | tigersforhire wrote:
         | I think one reason is that it actually entails a pretty big
         | lift from LLVMs side since it would introduce a new invariant
         | that needs to be upheld by optimization passes and code
         | generators.
         | 
         | I've heard rumours that Google have done some work internally
         | in this area, but it was never open sourced or upstreamed.
        
           | staticassertion wrote:
           | The thing is that this issue predates LLVM. It just feels
           | like the sort of thing that would have been brought up really
           | really early in the process, like as soon as anyone used it
           | for any real world project.
           | 
           | I imagine it's not straightforward, just seems like the
           | effort would have started earlier.
        
             | vlovich123 wrote:
             | Most projects targeting binaries provide coarse escape
             | hatches that work well enough (in the form of asm
             | volatile). This is a new space where we now need to persist
             | the optimization to work correctly through one AOT pass and
             | then a totally separate JIT which is a new thing and I'm
             | not surprised there's work to be done.
        
               | staticassertion wrote:
               | That's true - we're definitely working with much more
               | complex compilation pipelines now.
        
       | adrian17 wrote:
       | > packaging a library as an npm module using wasm-pack (...) the
       | code would be optimized twice before being executed, first by
       | LLVM and then by the Turbofan JIT compiler
       | 
       | Actually, that's not entirely true; if running wasm-pack, there's
       | another optimizer `wasm-opt`, running on output of llvm and wasm-
       | bindgen.
       | 
       | I've found it able to produce measurable improvements in speed
       | and size of the produced .wasm - which is quite surprising to me,
       | given it's basically a set of simple (compared to llvm)
       | optimization passes running on top of whatever llvm already
       | produced, with none of the metadata. However, this also means it
       | can easily do unexpected things like inlining a
       | `#[inline(never)]` function (because again, it only sees the
       | .wasm file, with none of rust or llvm metadata) - I stumbled upon
       | this several times when trying to profile wasm code in browsers.
       | 
       | This also means that if llvm ever supported constant-time
       | semantics, wasm-opt would happily ignore these too.
        
         | codeflo wrote:
         | You really do need to look at the whole chain. Of course, if
         | Wasm had constant-time annotations as suggested by the article
         | author, you'd expect wasm-opt to respect those.
         | 
         | Then there are steps below that layer to consider as well.
         | Maybe not so relevant when targeting Wasm, but x86 code is
         | increasingly executed inside emulators on ARM chips. Do those
         | respect the constant-timeness?
         | 
         | And what about processor microcode and fused instructions, can
         | a future CPU include an optimization that will un-constant-time
         | your code? (In other words: I really don't know, are there
         | constant-time guarantees made by the ISA?)
        
           | woodruffw wrote:
           | > (In other words: I really don't know, are there constant-
           | time guarantees made by the ISA?)
           | 
           | Not on AMD64, at least: neither Intel nor AMD will guarantee
           | the timing behavior or timing complexity of an instruction
           | between processors. REP prefixes with string/data operations
           | exemplify this -- they historically had data-dependent
           | timings, but have become increasingly decoupled as both Intel
           | and AMD have shoved "fast string" modes into ucode.
        
       | rwilson4 wrote:
       | Am I the only one who clicked on this expecting to read about the
       | barrier method for interior point algorithms?
        
       | akireu wrote:
        
       | codeflo wrote:
       | We pay a very heavy price for the complexity of modern compilers:
       | slow compilation times even on crazy fast hardware, real-world
       | bugs from undefined behavior propagation, and now here, leaking
       | cryptographic secrets unless heroic engineering efforts are made
       | to prevent it.
       | 
       | What we get in return for all that pain is slightly faster
       | execution -- in theory. A recent post on HN actually showed that
       | at least in some cases, modern LLVM compiles to code that
       | actually runs 1-2% slower than an ancient LLVM version.
       | 
       | Shouldn't we conclude from all this that what we need is a
       | movement to go back to simple, deterministic and fast compilers?
        
         | flerchin wrote:
         | > What we get in return for all that pain is slightly faster
         | execution
         | 
         | We also get protections against whole classes of security bugs,
         | ala Spectre and other vulns. Some of those protections make
         | speed tradeoffs.
        
           | codeflo wrote:
           | I don't agree that exploit mitigation is where the bulk of
           | the complexity in the compiler comes from. And if anything,
           | with all the UB inference going on, modern compilers might be
           | more likely to compile exploitable bugs into your code than
           | old ones were. Several well-known examples of this happening
           | exist.
           | 
           | (To explain: A decade ago, if there was a code path where you
           | dereference null, you would get a clean crash. Not pretty,
           | and potentially a denial of service, but usually not further
           | exploitable. Nowadays, the compiler will infer that this path
           | is not taken, eliminate the if, potentially eliminate other
           | checks as well because they are then reasoned to be
           | redundant, and then randomly execute _something_. This is
           | practically more dangerous in a lot more situations than
           | Spectre ever was.)
        
             | flerchin wrote:
             | It's pretty easy to disable the spectre mitigations, and
             | pretty easy to measure the performance impact (~10% in some
             | workloads).
        
         | bastawhiz wrote:
         | It would seem to me that your comment only really applies to C
         | or C++ or other similar languages. Modern JavaScript compilers
         | can compile and run code orders of magnitude faster than what
         | was possible fifteen years ago. Many languages have seen
         | dramatic compiler improvements.
         | 
         | Maybe the problem is that making big improvements to a compiler
         | for a fifty year old language that sits pretty close to the
         | metal is getting increasingly difficult because the people
         | writing the compilers are running out of clever tricks.
        
           | codeflo wrote:
           | With all respect, we're discussing an article about the
           | difficulty of balancing performance and security in modern
           | compilers in the context of implementing cryptographic
           | primitives. You might use those primitives from JavaScript
           | (Node.js links OpenSSL, for example), not typically implement
           | them in JavaScript.
        
             | bastawhiz wrote:
             | One of the two compilers discussed in the article is
             | Turbofan because the code in question is being invoked from
             | JavaScript, so I'm not sure how you think JavaScript isn't
             | relevant. We live in an age where not everything, including
             | cryptography, needs to traverse C or C++ to reach machine
             | code (see: Java, Go, etc).
             | 
             | Plenty of JavaScript and WASM exists for cryptography
             | purposes, for what it's worth, because Node isn't the only
             | runtime and "native" code isn't easily portable.
        
       | SkyMarshal wrote:
       | If it's not clear from the title, this article is about
       | maintaining the constant-time property of Rust cryptographic
       | libraries when compiler optimizations tend to compromise that
       | property.
       | 
       | There should probably be some kind ----constant-time compiler
       | flag to prevent the compiler from compromising that property when
       | it's a higher priority than raw performance.
        
         | vlovich123 wrote:
         | There's so many optimization passes that happen in a compiler
         | that I doubt such a flag is feasible. The CT types work is
         | probably a better avenue.
        
       ___________________________________________________________________
       (page generated 2022-01-27 23:02 UTC)