[IR] Accept non-Instruction in BinaryOperator::CreateWithCopiedFlags() (NFC)
authorNikita Popov <npopov@redhat.com>
Fri, 21 Jul 2023 07:58:22 +0000 (09:58 +0200)
committerNikita Popov <npopov@redhat.com>
Fri, 21 Jul 2023 08:05:52 +0000 (10:05 +0200)
The underlying copyIRFlags() API accepts arbitrary values and can
work with flags on operators (i.e. instructions or constant
expressions). Remove the arbitrary limitation that the
CreateWithCopiedFlags() API imposes, so we can directly pass through
values matched by PatternMatch, which can be constant expressions.

The attached test case works fine now, but would crash with an
upcoming change to not produce and constant expressions.

llvm/include/llvm/IR/InstrTypes.h
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/and-xor-or.ll

index 53d91eb..6095b0a 100644 (file)
@@ -245,7 +245,7 @@ public:
 #include "llvm/IR/Instruction.def"
 
   static BinaryOperator *
-  CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Instruction *CopyO,
+  CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Value *CopyO,
                         const Twine &Name = "",
                         Instruction *InsertBefore = nullptr) {
     BinaryOperator *BO = Create(Opc, V1, V2, Name, InsertBefore);
index 3f8660d..e335bcc 100644 (file)
@@ -2131,10 +2131,9 @@ static Instruction *canonicalizeLogicFirst(BinaryOperator &I,
     llvm_unreachable("Unexpected BinaryOp!");
   }
 
-  auto *Add = cast<BinaryOperator>(Op0);
   Value *NewBinOp = Builder.CreateBinOp(OpC, X, ConstantInt::get(Ty, *C));
   return BinaryOperator::CreateWithCopiedFlags(Instruction::Add, NewBinOp,
-                                               ConstantInt::get(Ty, *C2), Add);
+                                               ConstantInt::get(Ty, *C2), Op0);
 }
 
 // binop(shift(ShiftedC1, ShAmt), shift(ShiftedC2, add(ShAmt, AddC))) ->
index 2876225..e03a768 100644 (file)
@@ -4756,3 +4756,25 @@ define i8 @canonicalize_logic_first_xor_bad_constants2(i8 %x) {
   %r = xor i8 %a, 32  ; 00100000
   ret i8 %r
 }
+
+@g = external global i8
+
+define i32 @canonicalize_logic_first_constexpr(i32 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_constexpr
+; CHECK-SAME: (i32 [[X:%.*]]) {
+; CHECK-NEXT:    ret i32 and (i32 add (i32 ptrtoint (ptr @g to i32), i32 48), i32 -10)
+;
+  %a = add i32 ptrtoint (ptr @g to i32), 48
+  %r = and i32 %a, -10
+  ret i32 %r
+}
+
+define i32 @canonicalize_logic_first_constexpr_nuw(i32 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_constexpr_nuw
+; CHECK-SAME: (i32 [[X:%.*]]) {
+; CHECK-NEXT:    ret i32 and (i32 add (i32 ptrtoint (ptr @g to i32), i32 48), i32 -10)
+;
+  %a = add nuw i32 ptrtoint (ptr @g to i32), 48
+  %r = and i32 %a, -10
+  ret i32 %r
+}