{"push_id":1210161322,"size":1,"distinct_size":1,"ref":"refs/heads/master","head":"c7bcac6ed97b5525903a4d7953098f3d23b84fb6","before":"d6d8d1788638385c8fad0a25d7456070746d05e6","commits":[{"sha":"c7bcac6ed97b5525903a4d7953098f3d23b84fb6","author":{"name":"Tobias Grosser","email":"36c5bbefeb290c7a456f392d21ced31cf0271e32@grosser.es"},"message":"[InstCombine] Enable cast-folding in logic(cast(icmp), cast(icmp))\n\nSummary:\nCurrently, InstCombine is already able to fold expressions of the form `logic(cast(A), cast(B))` to the simpler form `cast(logic(A, B))`, where logic designates one of `and`/`or`/`xor`. This transformation is implemented in `foldCastedBitwiseLogic()` in InstCombineAndOrXor.cpp. However, this optimization will not be performed if both `A` and `B` are `icmp` instructions. The decision to preclude casts of `icmp` instructions originates in r48715 in combination with r261707, and can be best understood by the title of the former one:\n\n> Transform (zext (or (icmp), (icmp))) to (or (zext (cimp), (zext icmp))) if at least one of the (zext icmp) can be transformed to eliminate an icmp.\n\nApparently, it introduced a transformation that is a reverse of the transformation that is done in `foldCastedBitwiseLogic()`. Its purpose is to expose pairs of `zext icmp` that would subsequently be optimized by `transformZExtICmp()` in InstCombineCasts.cpp. Therefore, in order to avoid an endless loop of switching back and forth between these two transformations, the one in `foldCastedBitwiseLogic()` has been restricted to exclude `icmp` instructions which is mirrored in the responsible check:\n\n`if ((!isa<ICmpInst>(Cast0Src) || !isa<ICmpInst>(Cast1Src)) && ...`\n\nThis check seems to sort out more cases than necessary because:\n- the reverse transformation is obviously done for `or` instructions only\n- and also not every `zext icmp` pair is necessarily the result of this reverse transformation\n\nTherefore we now remove this check and replace it by a more finegrained one in `shouldOptimizeCast()` that now rejects only those `logic(zext(icmp), zext(icmp))` that would be able to be optimized by `transformZExtICmp()`, which also avoids the mentioned endless loop. That means we are now able to also simplify expressions of the form `logic(cast(icmp), cast(icmp))` to `cast(logic(icmp, icmp))` (`cast` being an arbitrary `CastInst`).\n\nAs an example, consider the following IR snippet\n\n```\n%1 = icmp sgt i64 %a, %b\n%2 = zext i1 %1 to i8\n%3 = icmp slt i64 %a, %c\n%4 = zext i1 %3 to i8\n%5 = and i8 %2, %4\n```\n\nwhich would now be transformed to\n\n```\n%1 = icmp sgt i64 %a, %b\n%2 = icmp slt i64 %a, %c\n%3 = and i1 %1, %2\n%4 = zext i1 %3 to i8\n```\n\nThis issue became apparent when experimenting with the programming language Julia, which makes use of LLVM. Currently, Julia lowers its `Bool` datatype to LLVM's `i8` (also see https://github.com/JuliaLang/julia/pull/17225). In fact, the above IR example is the lowered form of the Julia snippet `(a > b) & (a < c)`. Like shown above, this may introduce `zext` operations, casting between `i1` and `i8`, which could for example hinder ScalarEvolution and Polly on certain code.\n\nReviewers: grosser, vtjnash, majnemer\n\nSubscribers: majnemer, llvm-commits\n\nDifferential Revision: https://reviews.llvm.org/D22511\n\nContributed-by: Matthias Reisinger","distinct":true,"url":"https://api.github.com/repos/llvm-project/llvm-project/commits/c7bcac6ed97b5525903a4d7953098f3d23b84fb6"}]}
{"actor":{"display_login":"chapuni"}}